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

时间:2014-06-11 23:46:23

标签: 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);
}

我得到的每个执行的值都不同,例如:

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'实际存储?

2 个答案:

答案 0 :(得分:10)

int a = "abcd";

这在C中是非法的。

好吧,有点儿。对于这种事情,C标准实际上并没有使用“非法”一词。准确地说,它是约束违规,这意味着任何符合标准的编译器必须发出诊断消息(可能是非致命警告)。

表达式"abcd"是一个数组表达式,类型为char[5](字母为4,终止\0'为1)。在大多数情况下,包括这个(如果它是有效的),数组表达式被隐式转换为指向数组的第一个元素的指针。转换后,该值的类型为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);

答案 1 :(得分:0)

回答这个问题的最有效方法可能是漫游问题代码:

#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是变量存储在内存中的内存地址,在您的系统中看起来像15508632120x93E6DF1。该值不是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’     }