&"suchString" 的 return 值是多少?
What is the return value of &"suchString"?
这段代码的输出:
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
是:
suchString �WO:+(or any unknown symbols)
有什么不同,为什么输出不一样?
编辑
如果您尝试按如下方式消除 & 运算符:
char* str1 = "suchString";
printf("%s %s\n", "suchString", &str1);
输出与第一段代码相同。
现在,"suchString" 与 &"suchString" 的相同之处是什么?
这个:
&"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);
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
%s
说明符需要一个 char*
类型的参数,它必须是一个指向字符串的指针。您提供了 char (*)[11]
和 char**
类型的参数。您的代码具有未定义的行为,这意味着原则上它可以做任何事情。
字符串文字是一个数组。数组的地址指的是与数组第一个元素的地址相同的内存位置,但它是不同的类型。仅将 "suchString"
作为第二个参数传递是正确的,因为数组 "decays" 指向指向其第一个元素的指针。
在所有指针都具有相同表示的实现中(这是典型的但不是必需的),将指针传递到相同的内存位置但类型错误很可能 "work"。 printf
的特殊之处在于它可以接受不同类型的参数,因此编译器不一定能诊断出类型错误。对于非可变函数,这样的错误可能会在编译时被拒绝。
str1
是指针,不是数组。您已将其初始化为指向字符串文字的初始字符。您可以将 str1
传递给 printf
,但 &str1
是指针对象的地址,它不仅类型错误,而且根本不指向字符串。因此输出是垃圾。
如果要打印字符串值,可以这样做:
const char* str1 = "suchString";
printf("%s %s\n", "suchString", str1);
(我添加了 const
所以如果您尝试修改字符串文字的内容,编译器会报错。)
这段代码的输出:
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
是:
suchString �WO:+(or any unknown symbols)
有什么不同,为什么输出不一样?
编辑 如果您尝试按如下方式消除 & 运算符:
char* str1 = "suchString";
printf("%s %s\n", "suchString", &str1);
输出与第一段代码相同。 现在,"suchString" 与 &"suchString" 的相同之处是什么?
这个:
&"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);
char* str1 = "suchString";
printf("%s %s\n", &"suchString", &str1);
%s
说明符需要一个 char*
类型的参数,它必须是一个指向字符串的指针。您提供了 char (*)[11]
和 char**
类型的参数。您的代码具有未定义的行为,这意味着原则上它可以做任何事情。
字符串文字是一个数组。数组的地址指的是与数组第一个元素的地址相同的内存位置,但它是不同的类型。仅将 "suchString"
作为第二个参数传递是正确的,因为数组 "decays" 指向指向其第一个元素的指针。
在所有指针都具有相同表示的实现中(这是典型的但不是必需的),将指针传递到相同的内存位置但类型错误很可能 "work"。 printf
的特殊之处在于它可以接受不同类型的参数,因此编译器不一定能诊断出类型错误。对于非可变函数,这样的错误可能会在编译时被拒绝。
str1
是指针,不是数组。您已将其初始化为指向字符串文字的初始字符。您可以将 str1
传递给 printf
,但 &str1
是指针对象的地址,它不仅类型错误,而且根本不指向字符串。因此输出是垃圾。
如果要打印字符串值,可以这样做:
const char* str1 = "suchString";
printf("%s %s\n", "suchString", str1);
(我添加了 const
所以如果您尝试修改字符串文字的内容,编译器会报错。)