简体   繁体   English

sizeof() 如何与取消引用一起工作?

[英]How does sizeof() work with a dereference?

A recent code sample i saw:我最近看到的一个代码示例:

#include <stdio.h>
#include <stdlib.h>

struct x {
       int a;
       int b;
};

int main(void) {

    struct x *ptr = malloc(sizeof(*ptr));
    return 0;
}
  • How does sizeof(*ptr) even work? sizeof(*ptr)甚至如何工作?

  • How can a undefined pointer be dereferenced and be given to sizeof() and yield the correct size?如何取消引用未定义的指针并将其提供给sizeof()并产生正确的大小? (surely it should result in undefined behavior since its undefined) (当然它应该导致未定义的行为,因为它未定义)

  • Lastly does the C standard define this sort of behavior at all?最后,C 标准是否定义了这种行为? (maybe showing it is legal in C, i could not find anything) (也许表明它在 C 中是合法的,我找不到任何东西)

sizeof is not a function call, it is an operator . sizeof不是 function 调用,它是一个operator It does not work on the value of ptr , but its type.它不适用于ptr的值,而是它的类型。 ptr has been declared to be of type struct x* and so the compiler knows that sizeof(*ptr) is equivalent to sizeof(struct x) . ptr已被声明为struct x*类型,因此编译器知道sizeof(*ptr)等价于sizeof(struct x)

Demonstration .示范

ptr is not actually dereferenced here. ptr在这里实际上并没有被取消引用。 The operand of the sizeof operator, in this case the expression *ptr , is looked at only for its type. sizeof运算符的操作数,在本例中为表达式*ptr ,仅查看其类型。

This is spelled out in section 6.5.3.4p2 of the C standard regarding the sizeof operator:这在C 标准的第 6.5.3.4p2 节中关于sizeof运算符进行了详细说明:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. sizeof运算符产生其操作数的大小(以字节为单位),它可以是表达式或带括号的类型名称。 The size is determined from the type of the operand.大小由操作数的类型决定。 The result is an integer.结果是 integer。 If the type of the operand is a variable length array type, the operand is evaluated;如果操作数的类型是变长数组类型,则计算操作数; otherwise, the operand is not evaluated and the result is an integer constant否则,不计算操作数,结果为 integer 常量

In this particular case, *ptr is not evaluated but it is seen to have type struct x , so sizeof(*ptr) evaluates to a constant which is the size in bytes of struct x .在这种特殊情况下, *ptr没有被评估,但它被认为具有struct x类型,因此sizeof(*ptr)评估为一个常量,即struct x的字节大小。

The sizeof operator takes an expression or a parenthesized type as its argument. sizeof运算符将表达式或带括号的类型作为其参数。 It does not evaluate its argument unless that argument is a variable length array.除非该参数是可变长度数组,否则它不会评估其参数。 Either way, the size is determined from the type of the operand.无论哪种方式,大小都是由操作数的类型决定的。

So, given a pointer int *p , sizeof *p yields the size of an int since the expression *p has type int .因此,给定一个指针int *psizeof *p产生一个int的大小,因为表达式*p具有int类型。 There is no evaluation and hence no dereference here.没有评估,因此这里没有取消引用。 Alternatively, you could use sizeof(int) to find the size of an int .或者,您可以使用sizeof(int)来查找int的大小。 In the first case the operand is the expression *p , and in the second case the operand is the parenthesized type (int) .在第一种情况下,操作数是表达式*p ,在第二种情况下,操作数是带括号的类型(int)

It may be worth commenting that struct x *ptr = malloc(sizeof(*ptr));值得一提的是struct x *ptr = malloc(sizeof(*ptr)); is a useful C idiom.是一个有用的 C 成语。 The parentheses around *ptr are not needed since *ptr is an expression, not a type:不需要 * *ptr周围的括号,因为*ptr是表达式,而不是类型:

struct x *ptr = malloc(sizeof *ptr);

This construct is clear and easy to maintain when types change, eg, when struct x is no longer desired, but now struct y is needed, there is only one thing to change:当类型发生变化时,这种结构清晰且易于维护,例如,当不再需要struct x ,但现在需要struct y时,只需更改一件事:

struct y *ptr = malloc(sizeof *ptr);

After this one simple change ptr is a pointer to struct y , and the correct amount of memory has been allocated for one struct y .在这个简单的更改ptr是指向struct y的指针之后,正确数量的 memory 已分配给一个struct y

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM