此代码片段的输出:
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
是:
suchString WO:+(或任何未知符号)
有什么不同,为什么输出不一样?
修改 如果你试图消除&运算符如下:
char* str1 = "suchString";
printf("%s %s\n", "suchString", &str1);
输出与第一段代码相同。 现在,“suchString”是如何与&“suchString”相同的?
答案 0 :(得分:3)
此:
&"suchString"
获取字符串文字的地址。字符串文字是数组,而不是指针。
如果编译时启用了警告,那么您已经知道了:
prog.c:5:14: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[11]' [-Wformat=]
printf("%s %s\n", &"suchString", &str1);
~^ ~~~~~~~~~~~~~
prog.c:5:17: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'char **' [-Wformat=]
printf("%s %s\n", &"suchString", &str1);
~^ ~~~~~
第一个是char (*)[11]
类型,而第二个类型是char **
。
对于垃圾值,您提供了指向%s
格式的指针的地址,从而破坏了打印。如果您使用%p
代替,则会看到正在打印的地址,例如" 0x7ffe676f5588"
在尝试使用printf()
中的字符串说明符打印字符串文字的地址时也是如此。
此外,你应该转发void*
,如下所示:
printf("%p %p\n", (void*)"suchString", (void*)str1);
答案 1 :(得分:1)
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
%s
说明符需要类型为char*
的参数,该参数必须是指向字符串的指针。您提供了char (*)[11]
和char**
类型的参数。您的代码具有未定义的行为,这意味着原则上它可以做任何事情。
字符串文字是一个数组。阵列的地址指的是与阵列的第一个元素的地址相同的存储位置,但它是不同类型的地址。仅传递"suchString"
作为第二个参数是正确的,因为数组"衰变"指向其第一个元素的指针。
在所有指针具有相同表示(通常但不是必需)的实现中,将指针传递到相同的内存位置但是类型错误可能会工作"。 printf
的特殊之处在于它可以接受不同类型的参数,因此编译器无法诊断类型错误。对于非可变函数,这样的错误可能会在编译时被拒绝。
str1
是一个指针,而不是一个数组。您已将其初始化为指向字符串文字的初始字符。您可以将str1
传递给printf
,但&str1
是指针对象的地址,它不仅类型错误,而且根本不指向字符串。因此输出是垃圾。
如果要打印字符串值,可以执行以下操作:
const char* str1 = "suchString";
printf("%s %s\n", "suchString", str1);
(我已添加const
,因此如果您尝试修改字符串文字的内容,编译器会抱怨。)