[英]What happens when I assign a string to an 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);
}
我得到的每个执行的值都不同,例如:
a as string witn & = "?????W?
a as int witn no & = 130694946
a as int witn & = 1475726188
要么
a as string witn & = "?O?Kp\?
a as int witn no & = 55557922
a as int witn & = 1550863212
这些价值观是什么? 为什么他们总是不同? 什么是'a'实际存储?
int a = "abcd";
这在C中是非法的。
好吧,有点。 对于这种事情,C标准实际上并没有使用“非法”一词。 准确地说,这是一个约束违规 ,这意味着任何符合标准的编译器必须发出诊断消息(这可能是一个非致命的警告)。
表达式"abcd"
是char[5]
类型的数组表达式(4表示字母加1表示终止\\0'
)。 在大多数情况下,包括这个(如果它是有效的),数组表达式被隐式转换为指向数组的第一个元素的指针。 在转换之后,值的类型为char*
,它是指向'a'
的指针。
没有从char*
到int
隐式转换,这就是初始化无效的原因。 您可以添加强制转换,这是一种显式转换:
int a = (int)"abcd";
这将存储在a
字符串的内存地址,从转换char*
来int
。 在许多系统中,这种转换虽然合法,却会产生垃圾; 例如,在我输入的系统上, char*
是64位, int
只是32位。
旧版C语言(早于1989年)的编译器对隐式转换更加宽松,通常允许将整数和指针相互分配。 更现代的编译器,即使他们要求他们诊断出这个错误,也可能(或可能不会)生成执行隐式转换的代码。 (严格地说,行为是未定义的,但隐式转换很常见。)
如果您的编译器拒绝
int a = "abcd";
它正在做它的工作。 如果它只是警告你,它仍然在C标准方面做它的工作,但它实际上并没有通过生成隐式转换对你有所帮助。
底线:分配给a
的值是垃圾,如果你的编译器没有抱怨它,找出你需要做什么选项来让它这样做。
至于printf
调用的输出:
printf("a as string witn & = %s\n", &a);
%s
需要一个指向字符串的char*
参数。 &a
的类型为int*
,并不指向字符串。 行为未定义。 很可能printf
将从a
开头打印垃圾字节,直到碰巧遇到空字节(或崩溃)。
不要那样做。
printf("a as int witn no & = %d\n", a);
如果你的程序还没有在这一点上坠毁,这种打印的值a
。 该值是垃圾,通常可能是字符串文字地址的转换值,或者只是该地址的低32位。
printf("a as int witn & = %d\n", &a);
%d
需要int
类型的参数。 &a
的类型为int*
。 未定义的行为。 这可能会打印的内存地址a
十进制整数。 不要那样做。 如果你真的想打印的地址a
,做正确的做法是:
printf("&a = %p\n", (void*)&a);
也许回答这个问题的最有效方法是漫步问题代码:
#include <stdio.h>
int main(void) {
int a = "abcd";
上面的行声明了一个名为a的int,并使用字符串“abcd”的地址初始化a。 这一行将导致编译器变得有点脾气暴躁,因为它会抱怨类似: warning: initialization makes integer from pointer without a cast
。
printf("a as string witn & = %s\n", &a);
上面一行的对象似乎是打印一个字符串。 不幸的是, &a
是变量存储在内存中的内存地址,看起来它就像你的系统上的1550863212
或0x93E6DF1
。 该值不是ASCII或UTF-8字符串; 因此它似乎打印出垃圾: "?????W?
, "?O?Kp\\?
或者其他一些无意义的字符串,具体取决于a
的地址。 当然,这条线会让编译器变得更加脾气暴躁; format '%s' expects type 'char *', but argument 2 has type 'int *'
printf("a as int witn no & = %d\n", a);
上面的行尝试将a
的值打印为有符号整数。 它也将出现废话,因为价值a
是字符串“ABCD”的地址。 因此, a
(作为有符号整数)的值将是字符串“abcd”存储在存储器中的地址的有符号整数表示。
printf("a as int witn & = %d\n", &a);
上面的行尝试将a
的内存地址打印为有符号整数。 与其他人一样,这很可能再次显得无稽之谈。
printf("a as a string[%s]\n", a);
为了您的观赏乐趣,我添加了上面的行,输出:“ a as a string[abcd]
”。 这证明变量a
已成功初始化,尽管(再次)编译器认为我们疯了: warning: format '%s' expects type 'char *', but argument 2 has type 'int'
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.