将字符串分配给int时会发生什么?

use*_*125 2 c string int

如果我用字符串实例化一个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)

  • 在约束违规之后生成的任何可执行文件都有完全未定义的行为. (2认同)