在以下代码中,函数test
和test2
是否等效?
typedef int rofl;
void test(void) {
rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?
}
void test2(void) {
rofl * rofl = malloc(sizeof *rofl); // Is the final rofl here the VARIABLE?
}
换句话说:
rofl
中的sizeof(rofl)
是否正确选择rofl
类型?rofl
中的sizeof *rofl
是否正确选择了rofl
变量?注意:这是一个看起来很愚蠢的例子,但在实践中实际上可能会发生一个类型名称与变量名称相同的名称。因此问题。
答案 0 :(得分:27)
在这两种情况下,最后一个rofl
是变量名称。变量名一出现就在范围内;对于当前范围的其余部分,普通上下文(*)中的标识符始终表示变量名称。
sizeof
运算符不会为名称查找引入任何特殊情况。实际上,没有语言结构会使用标识符的隐藏含义。
在实践中,最好不要对类型和变量名使用相同的标识符。
(*)标识符有三个特殊的上下文:标签名称,结构标签和结构成员。但在所有其他上下文中,所有标识符共享一个公共名称空间:类型名称与变量名称与函数名称等没有明确的标识符名称空间。
这是一个人为的例子:
typedef int A; // "A" declared as ordinary identifier, meaning a type name
struct A { A A; }; // "A" declared as struct tag and member name -- OK as these are three different name spaces. Member type is "int"
A main() // int main() - ordinary context
{
struct A A(); // "A" declared as ordinary identifier, meaning a function name; hides line 1's A
// A C; // Would be error: ordinary A is a function now, not a typedef for int
struct A B; // OK, struct tags have separate name space
A:+A().A; // OK, labels and struct members have separate name space, calls function
goto A; // OK, label name space
}
答案 1 :(得分:13)
在此声明中
rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?
变量rofl
的名称隐藏了typedef名称rofl
。因此,在sizeof运算符中,使用了指针rofl
,该表达式具有类型int *
。
同样适用于此声明
rofl * rofl = malloc(sizeof *rofl);
除了使用带有解除引用的指针rofl
的表达式,该指针具有typedef名称rofl
的类型int
。
似乎由于这个C语法定义而引起混淆
sizeof unary-expression
sizeof ( type-name )
但是unary-expression
可以是一个主表达式,它是括在括号中的表达式。
来自C标准(6.5.1主表达式)
primary-expression:
( expression )
//...
因此,例如,如果x
是变量的名称,那么您可以编写
sizeof x
或
sizeof( x )
为清楚起见,您可以在sizeof运算符和主表达式之间插入空格
sizeof ( x )
operator primary expression
为了比较,考虑另一个一元运算符:一元加号。你可以写例如
+ x
或
+ ( x )
现在只需将一元加号替换为另一个一元运算符sizeof
。
至于隐藏名称,问题可以解析为结构,联合和枚举,因为它们的名称包含标记的关键字。
例如
typedef struct rofl { int x; } rofl;
void test(void) {
rofl * rofl = malloc(sizeof( struct rofl));
}
在使用sizeof运算符的此函数中,使用了类型名称struct rofl
。
在此功能中
typedef struct rofl { int x; } rofl;
void test(void) {
rofl * rofl = malloc(sizeof( rofl));
}
使用sizeof运算符时,使用了具有变量rofl
的主表达式,其类型为struct rofl *
。
答案 2 :(得分:2)
没有涉及“挑选”或“选择”。在这两种情况下,由于范围规则,每个rofl
调用中引用的sizeof
是变量,而不是类型。变量在内部范围声明,因此会覆盖类型名称。 sizeof
运算符的参数括号内无关紧要。
祝你好运。