C 对存在同名类型的变量使用sizeof是否定义良好?
这是定义良好的行为还是未定义/以其他方式定义了将在其上运行的C 对存在同名类型的变量使用sizeof是否定义良好?,c,sizeof,undefined-behavior,C,Sizeof,Undefined Behavior,这是定义良好的行为还是未定义/以其他方式定义了将在其上运行的foo(数据类型或标识符)sizeof typedef int foo; int main(int argc, char *argv[]) { char foo; printf ("%u\r\n", sizeof(foo)); return 0; } 如果定义良好,是否有一种方法可以获得数据类型foo的大小,而不声明该类型的变量,只在其上使用sizeof?本地char foo在其范围内完全隐藏typedef
foo
(数据类型或标识符)sizeof
typedef int foo;
int main(int argc, char *argv[])
{
char foo;
printf ("%u\r\n", sizeof(foo));
return 0;
}
如果定义良好,是否有一种方法可以获得数据类型
foo
的大小,而不声明该类型的变量,只在其上使用sizeof
?本地char foo
在其范围内完全隐藏typedef int foo
。一旦名称foo
被隐藏,您就无法观察它。尝试创建第二个typedef foo foo\t
,或重命名某些内容以避免“冲突”
这是定义明确的行为还是未定义的行为
这是定义明确的行为
在代码中
printf ("%u\r\n", sizeof(foo));
foo
是明确的。局部或内部的foo
“阴影”(或隐藏)外部的foo
。因此,它本质上是
printf ("%u\r\n", sizeof(char));
引用第§6.2.1章“标识符范围”中的C11
(重点)
如果标识符以相同的名称指定两个不同的实体
空间,范围可能重叠。如果是这样,一个实体的范围(内部范围)将严格地在另一个实体的范围(外部范围)之前结束在内部范围内,标识符指定在内部范围内声明的实体;外部作用域中声明的实体在内部作用域中隐藏(不可见)。
现在,回答第二部分
如果定义良好,是否有一种方法可以获得数据类型foo
的大小,而不声明该类型的变量仅在其上使用sizeof
好的,内部foo
标识符的范围在其定义之后开始(作为char
类型变量)。因此,如果在定义变量foo
之前使用foo
(typedef
ed类型),您将实际看到全局定义,因为到那时为止,变量foo
不存在以“隐藏”全局标识符foo
正如by中所提到的,您当然可以执行以下操作
#include <stdio.h>
typedef int foo;
int main(void)
{
printf ("%zu\n", sizeof foo); /* will cosider the global */
char foo = 0; /* Global definition gets shadowed here*/
printf ("%zu\n", sizeof foo); /* The local definition of 'foo' is only visible*/
/* till the end of the block (function)*/
return 0;
}
#包括
typedef int-foo;
内部主(空)
{
printf(“%zu\n”,sizeof foo);/*将对全局*/
char foo=0;/*全局定义在此处被隐藏*/
printf(“%zu\n”,sizeof foo);/*仅可见“foo”的本地定义*/
/*直到块的末尾(函数)*/
返回0;
}
也就是说,
sizeof
操作符的结果类型是size\t
。您应该使用%zu
格式说明符打印结果。首先根据C标准(6.5.3.4运算符的大小和对齐方式)
2 sizeof运算符生成其操作数的大小(以字节为单位),其中
可以是表达式或类型的括号名称大小
由操作数的类型确定。结果为
整数。如果操作数的类型是可变长度数组类型,
计算操作数;否则,将不计算操作数并
结果是一个整数常量
因此,sizeof运算符的操作数类型决定了操作数的大小。因此,可以互换使用表达式或某些类型定义
请注意,sizeof运算符中使用的表达式未进行求值
比如你可以写
int x = 10;
printf( "%zu\n", sizeof( ++x ) );
在printf之后,x的值与printf之前的值相同
至于您的代码片段,似乎您犯了一个错误。我想你的意思是
typedef int foo;
int main(int argc, char *argv[])
{
foo exp;
printf ("%zu\r\n", sizeof( exp ));
return 0;
}
当然,不需要创建foo类型的对象。你可以写得很简单
printf ("%zu\r\n", sizeof( foo ));
至于你的原始代码
typedef int foo;
int main(int argc, char *argv[])
{
char foo;
printf ("%u\r\n", sizeof(foo));
return 0;
}
然后,函数main的块范围中的标识符名称foo
将在全局范围和语句中隐藏类型定义foo
printf ("%u\r\n", sizeof(foo));
相当于
printf ("%u\r\n", sizeof( char ));
在C中,在这种情况下不能引用foo的全局定义。C没有明确的作用域解析,因此当打开一个新的作用域时,标识符(变量名、typedef名、结构名等)可以被重用和覆盖。当一个标识符被重用时,该标识符所持有的上一个上下文将不再可见 在特定代码中,
typedef
的作用域是全局的,因此typedef在编译包中随处可见。但是,您可以使用函数声明打开一个新范围,并在该新范围中定义一个使用与typedef
相同标识符的变量。现在,该标识符引用的是变量而不是类型;也就是说,在变量范围结束(函数结束)之前,typedef
完全隐藏
回想一下,C是线性编译的,因此您可以这样做,以避免出现屏蔽:
#include <stdio.h>
typedef int foo;
int main()
{
printf ("%zu\n", sizeof (foo)); /* #1 */
char foo;
printf ("%zu\n", sizeof foo); /* #2 */
return 0;
}
#包括
typedef int-foo;
int main()
{
printf(“%zu\n”,sizeof(foo));/*#1*/
查富;
printf(“%zu\n”,大小为foo);/*#2*/
返回0;
}
在第#1点,请注意变量char foo
的作用域尚未打开,因为编译器尚未到达其声明。(编译器所要做的就是在堆栈上为变量分配空间)
因此,此时foo
的用法仍然是参照全局定义的typedef
当您点击#2时,变量被声明,变量的生存期正式开始,这意味着标识符现在正用于另一个实体。它将当前块范围(由函数声明启动)从foo
的全局定义中屏蔽
这是良好的文档行为;网上有一份C标准草案,但必须购买已发布的标准。草案第节说