如果我用字符串实例化一个int,那个int的值实际上是什么?例如,对于以下代码:
#include <stdio.h>
int main(void) {
int a = "abcd";
printf("a as string witn & = %s\n", &a);
printf("a as int witn no & = %d\n", a);
printf("a as int witn & = %d\n", &a);
}
Run Code Online (Sandbox Code Playgroud)
我得到的每个执行的值都不同,例如:
a as string witn & = "?????W?
a as int witn no & = 130694946
a as int witn & = 1475726188
Run Code Online (Sandbox Code Playgroud)
要么
a as string witn & = "?O?Kp\?
a as int witn no & = 55557922
a as int witn & = 1550863212
Run Code Online (Sandbox Code Playgroud)
这些价值观是什么?为什么他们总是不同?什么是'a'实际存储?
Kei*_*son 10
int a = "abcd";
Run Code Online (Sandbox Code Playgroud)
这在C中是非法的.
好吧,有点.对于这种事情,C标准实际上并没有使用"非法"一词.准确地说,这是一个约束违规,这意味着任何符合标准的编译器必须发出诊断消息(这可能是非致命的警告).
表达式"abcd"
是一个数组表达式,类型为char[5]
(字母为4,终止为1 \0'
).在大多数情况下,包括这个(如果它是有效的),数组表达式被隐式转换为指向数组的第一个元素的指针.在转换之后,值是类型char*
,它是指向的'a'
.
有没有隐含的从转换char*
到int
,这就是为什么这个初始化是无效的.您可以添加强制转换,这是一种显式转换:
int a = (int)"abcd";
Run Code Online (Sandbox Code Playgroud)
这将存储在a
字符串的内存地址中,从中转换char*
为int
.在许多系统中,这种转换虽然合法,却会产生垃圾; 例如,在我输入的系统上,a char*
是64位而a int
只是32位.
旧版C语言(早于1989年)的编译器对隐式转换更加宽松,通常允许将整数和指针相互分配.更现代的编译器,即使他们要求他们诊断出这个错误,也可能(或可能不会)生成执行隐式转换的代码.(严格地说,行为是未定义的,但隐式转换很常见.)
如果您的编译器拒绝
int a = "abcd";
Run Code Online (Sandbox Code Playgroud)
它正在做它的工作.如果它只是警告你,它仍然在C标准方面做它的工作,但它真的没有通过生成隐式转换对你有任何好处.
底线:分配给的值a
是垃圾,如果你的编译器没有抱怨它,找出你需要做什么选项来让它这样做.
至于你的printf
电话输出:
printf("a as string witn & = %s\n", &a);
Run Code Online (Sandbox Code Playgroud)
%s
需要一个char*
指向字符串的参数. &a
是类型int*
,并不指向字符串.行为未定义.很可能printf
会在开始时打印垃圾字节,a
直到碰巧遇到空字节(或崩溃).
不要那样做.
printf("a as int witn no & = %d\n", a);
Run Code Online (Sandbox Code Playgroud)
如果您的程序此时尚未崩溃,则会打印出值a
.该值是垃圾,通常可能是字符串文字地址的转换值,或者只是该地址的低32位.
printf("a as int witn & = %d\n", &a);
Run Code Online (Sandbox Code Playgroud)
%d
需要一个类型的参数int
.&a
是类型的int*
.未定义的行为.这可能会打印a
十进制整数的内存地址.不要那样做.如果你真的想打印地址a
,正确的方法是:
printf("&a = %p\n", (void*)&a);
Run Code Online (Sandbox Code Playgroud)