在这种情况下,C是否正确处理sizeof(...)和sizeof ...

cco*_*987 38 c sizeof unary-operator

在下面的代码中,功能testtest2等效的是什么?

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?
}
Run Code Online (Sandbox Code Playgroud)

换一种说法:

  1. 是否roflsizeof(rofl)正确挑选rofl 类型,因为括号?
  2. 是否roflsizeof *rofl正确地挑选rofl 可变的,因为一个缺少括号?

注意:这是一个看起来很愚蠢的例子,但在实践中实际上你可以使用与变量名相同的类型名称.因此问题.

M.M*_*M.M 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
}
Run Code Online (Sandbox Code Playgroud)


Vla*_*cow 13

在这个宣言中

rofl * rofl = malloc(sizeof(rofl)); // Is the final rofl here the TYPE?
Run Code Online (Sandbox Code Playgroud)

变量的名称rofl隐藏了typedef名称rofl.因此,在sizeof运算符中,使用rofl了表达式具有类型的指针int *.

这同样适用于此声明

rofl * rofl = malloc(sizeof *rofl); 
Run Code Online (Sandbox Code Playgroud)

除了使用带有解除引用指针的表达式,该指针rofl具有typedef rofl类型的类型int.

似乎由于这种C语法定义而产生混淆

sizeof unary-expression
sizeof ( type-name )
Run Code Online (Sandbox Code Playgroud)

但是,unary-expression可以是括在括号中的表达式的主表达式.

来自C标准(6.5.1主表达式)

primary-expression:
    ( expression )
    //...
Run Code Online (Sandbox Code Playgroud)

因此,例如,如果x是变量的名称,那么您可以编写

sizeof x 
Run Code Online (Sandbox Code Playgroud)

要么

sizeof( x )
Run Code Online (Sandbox Code Playgroud)

为清楚起见,您可以在sizeof运算符和主表达式之间插入空格

sizeof    ( x )
operator  primary expression
Run Code Online (Sandbox Code Playgroud)

为了比较,考虑另一个一元运算符:一元加号.你可以写例如

+ x
Run Code Online (Sandbox Code Playgroud)

要么

+ ( x )
Run Code Online (Sandbox Code Playgroud)

现在只需将一元加号替换为另一位一元运算符sizeof.

至于隐藏名称,问题可以解析为结构,联合和枚举,因为它们的名称包括标记的关键字.

例如

typedef struct rofl { int x; } rofl;

void test(void) {
    rofl * rofl = malloc(sizeof( struct rofl));
}
Run Code Online (Sandbox Code Playgroud)

在使用sizeof运算符的函数中,使用了type-name struct rofl.

而在这个功能

typedef struct rofl { int x; } rofl;

void test(void) {
    rofl * rofl = malloc(sizeof( rofl));
}
Run Code Online (Sandbox Code Playgroud)

使用sizeof运算符时,使用带有变量的主表达式,该变量rofl具有类型struct rofl *.