【问题标题】:Why does my homespun sizeof operator need a char* cast?为什么我的普通 sizeof 运算符需要 char* 演员表?
【发布时间】:2010-04-09 14:43:47
【问题描述】:

下面是不使用 sizeof 运算符求结构体大小的程序:

struct MyStruct
{
  int i;
  int j;
};

int main()
{
   struct MyStruct *p=0;
   int size = ((char*)(p+1))-((char*)p);
   printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
   return 0;
}

为什么需要对 char * 进行类型转换?

如果我不使用 char* 指针,则输出为 1 - 为什么?

【问题讨论】:

  • 提醒:结构的大小可能不等于其成员(字段)大小的总和。允许编译器在结构的成员之间插入填充字节。一个例子是在地址上对齐变量,以便处理器有效地获取。

标签: c


【解决方案1】:

因为指针运算以指向的类型为单位工作。例如:

int* p_num = malloc(10 * sizeof(int)); 
int* p_num2 = p_num + 5;

这里,p_num2 不指向p_num 之外的五个字节,它指向p_num 之外的五个整数。如果在您的机器上一个整数是 4 个字节宽,则存储在 p_num2 中的地址将比存储在 p_num 中的地址多 20 个字节。这样做的原因主要是因为指针可以像数组一样被索引。 p_num[5] 完全等同于 *(p_num + 5),因此指针运算始终以字节为单位是没有意义的,否则 p_num[5] 会给你一些从第二个整数中间开始的数据,而不是给你如您所料,第六个整数。

为了将特定数量的 字节 移动到指针之外,您需要将指针强制转换为指向保证正好为 1 字节宽的类型(char)。

另外,这里有一个错误:

printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);

您有两个格式说明符,但格式字符串后面只有一个参数。

【讨论】:

    【解决方案2】:

    如果我不使用 char* 指针,则输出为 1 - 为什么?
    因为operator- 遵循与operator+ 相同的指针算术规则。当您向指针添加 1 时,您增加了 sizeof(MyStruct),但如果没有强制转换,您将在指针的 operator- 中将字节差除以 sizeof(MyStruct)

    为什么不使用内置的sizeof() 运算符?

    【讨论】:

    • 如果你使用sizeof,一定要在指向的对象上使用它,而不是指针本身。 sizeof(p) 将为您提供指针的大小,而sizeof(*p) 将为您提供MyStruct 的大小。
    【解决方案3】:

    因为您想要以字节为单位的结构的大小。并且指针算术隐式使用类型大小。

    int* p;
    p + 5; // this is implicitly p + 5 * sizeof(int)
    

    通过转换为 char* 可以规避这种行为。

    【讨论】:

    • 好吧,sizeofchar 存储的任何单位返回大小(即 sizeof(char) 始终为 1)。这是典型实现中的字节数,但不需要如此......
    • 确实如此,但无论何时您要求字节类型,您都会得到答案 unsigned char :)
    【解决方案4】:

    指针算法是根据指针类型的大小来定义的。这就是允许(例如)指针算术和数组下标之间的等价性——*(ptr+n) 等价于ptr[n]。当您减去两个指针时,您会得到它们所指向的项目数的差异。转换为pointer to char 意味着它告诉您这些地址之间的字符数。由于 C 使 charbyte 本质上是等效的(即一个字节是一个字符所需的存储空间),这也是第一项占用的字节数。

    【讨论】:

      猜你喜欢
      • 2014-12-02
      • 2016-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-26
      • 2018-09-14
      • 1970-01-01
      • 2019-12-02
      相关资源
      最近更新 更多