Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 对存在同名类型的变量使用sizeof是否定义良好?_C_Sizeof_Undefined Behavior - Fatal编程技术网

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标准草案,但必须购买已发布的标准。草案第节说