为什么 sizeof 的赋值会改变从 size_t 赋值给 int 的变量类型?
Why does assignment from sizeof alter type of variable being assigned from size_t to int?
此程序编译时没有警告,并提供了预期的输出。
#include <stdio.h>
#include <stddef.h>
int i;
size_t s = sizeof(i);
int main(void){
printf("%zu \n", s);
}
但是这个程序没有编译,我观察到以下警告和错误:
#include <stdio.h>
#include <stddef.h>
int i;
size_t s;
s = sizeof(i);
int main(void){
printf("%zu \n", s);
}
警告和错误:
$ gcc -std=c99 -o sizeof_test sizeof_test.c
sizeof_test.c:6:1: warning: data definition has no type or storage class [enabled by default]
s = sizeof(i);
^
sizeof_test.c:6:1: warning: type defaults to ‘int’ in declaration of ‘s’ [enabled by default]
sizeof_test.c:6:1: error: conflicting types for ‘s’
sizeof_test.c:5:8: note: previous declaration of ‘s’ was here
size_t s;
^
sizeof_test.c: In function ‘main’:
sizeof_test.c:9:5: warning: format ‘%zu’ expects argument of type ‘size_t’, but argument 2 has type ‘int’ [-Wformat=]
printf("%zu \n", s);
^
这是 gcc
版本信息:
$ gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我的理解是,至少对于 c99 和可能更早的版本,sizeof
有一个 return 类型的 size_t
,例如 stated at cppreference.
如果是这样,那么从 sizeof
赋值怎么会导致某些隐式类型转换为 int
而不是作为 size_t
变量的直接初始化完成? s
和sizeof
运算符的return类型都不是int
,那么int
类型从何而来呢?
真正的问题是,你不能在所有函数之外赋值变量。
size_t s;
s = sizeof(i);
这两行被解释为:一个全局变量s
,类型为size_t
,以及另一个全局变量s
,类型为隐式int
(C99无效),用sizeof(i)
初始化。
如果你明白这一点,你就能理解所有的error/warning消息。它们要么与 s
的隐式 int
类型相关,要么与定义了两种不同类型的 s
相关。
问题是您只能在全局范围内定义变量(带有可选的初始值设定项)。你不能有可执行语句。
当编译器在全局范围内看到它时:
s = sizeof(i);
由于那里不能存在语句,因此假定它是一个变量声明。您收到的错误和警告如下:
- 由于声明没有定义类型,类型默认为
int
,您会收到针对这两种情况的警告。
- 然后你会得到类型冲突的错误,因为这个隐式定义的
int
与上一行定义的 size_t
同名。
- 有关无效
printf
格式说明符的警告也随之而来,因为 s
的最新定义是 int
。
此程序编译时没有警告,并提供了预期的输出。
#include <stdio.h>
#include <stddef.h>
int i;
size_t s = sizeof(i);
int main(void){
printf("%zu \n", s);
}
但是这个程序没有编译,我观察到以下警告和错误:
#include <stdio.h>
#include <stddef.h>
int i;
size_t s;
s = sizeof(i);
int main(void){
printf("%zu \n", s);
}
警告和错误:
$ gcc -std=c99 -o sizeof_test sizeof_test.c
sizeof_test.c:6:1: warning: data definition has no type or storage class [enabled by default]
s = sizeof(i);
^
sizeof_test.c:6:1: warning: type defaults to ‘int’ in declaration of ‘s’ [enabled by default]
sizeof_test.c:6:1: error: conflicting types for ‘s’
sizeof_test.c:5:8: note: previous declaration of ‘s’ was here
size_t s;
^
sizeof_test.c: In function ‘main’:
sizeof_test.c:9:5: warning: format ‘%zu’ expects argument of type ‘size_t’, but argument 2 has type ‘int’ [-Wformat=]
printf("%zu \n", s);
^
这是 gcc
版本信息:
$ gcc --version
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我的理解是,至少对于 c99 和可能更早的版本,sizeof
有一个 return 类型的 size_t
,例如 stated at cppreference.
如果是这样,那么从 sizeof
赋值怎么会导致某些隐式类型转换为 int
而不是作为 size_t
变量的直接初始化完成? s
和sizeof
运算符的return类型都不是int
,那么int
类型从何而来呢?
真正的问题是,你不能在所有函数之外赋值变量。
size_t s;
s = sizeof(i);
这两行被解释为:一个全局变量s
,类型为size_t
,以及另一个全局变量s
,类型为隐式int
(C99无效),用sizeof(i)
初始化。
如果你明白这一点,你就能理解所有的error/warning消息。它们要么与 s
的隐式 int
类型相关,要么与定义了两种不同类型的 s
相关。
问题是您只能在全局范围内定义变量(带有可选的初始值设定项)。你不能有可执行语句。
当编译器在全局范围内看到它时:
s = sizeof(i);
由于那里不能存在语句,因此假定它是一个变量声明。您收到的错误和警告如下:
- 由于声明没有定义类型,类型默认为
int
,您会收到针对这两种情况的警告。 - 然后你会得到类型冲突的错误,因为这个隐式定义的
int
与上一行定义的size_t
同名。 - 有关无效
printf
格式说明符的警告也随之而来,因为s
的最新定义是int
。