【问题标题】:printf string literal with address operator带有地址运算符的 printf 字符串文字
【发布时间】:2013-10-01 14:43:02
【问题描述】:
#include<stdio.h>

int main()
{
    printf("%s\n", "Hello");
    printf("%s\n", &"Hello");
    return 0;
}

Output : 
Hello
Hello

谁能向我解释为什么"Hello"&amp;"Hello" 会产生相同的结果?

【问题讨论】:

  • C 中没有引用。一元 &amp; 是地址运算符。
  • @alkis 你没有编辑标题?
  • 你使用哪个编译器,顺便说一句?
  • @devnull 我在 windows 上使用 dev-c++ 作为我的 ide(仅用于测试),它使用 Mingw,它是 GCC 的一个端口
  • @alkis 所以编译器没有任何选项来启用任何警告?

标签: c string printf address-operator


【解决方案1】:

&amp; 应用于“Hello”会产生一个指向该数组的指针(是的,它是一个数组,在这种情况下它不会衰减为指针)。

它仍然指向同一个位置,但它有不同的类型(它有char (*)[6],即指向6个字符数组的指针)。 printf 忽略指针的真实类型并将其视为 char *,因此它“有效”。


从技术上讲,对 printf 说明符使用“错误”对象类型是未定义的行为。打开警告应该在现代编译器中指出这一点。

【讨论】:

  • 谢谢。你真的帮了大忙。
  • 如,字面量"Hello" 衰减为指针char*,但&amp;"Hello" 不会衰减,它是char(*)[6] 类型的数组指针。
  • @Lundin 我的意思是,在应用&amp; 的上下文中,"Hello" 不会衰减为指针。
【解决方案2】:

这是因为字符串文字被视为const char 数组。代码相当于这样写:

char array [] = "Hello";
printf("%s\n", array);
printf("%s\n", &array);
  • 当您将数组名称传递给需要指针的函数时,数组“衰减”为指针。
  • 当你传递数组的地址时,你会得到一个数组指针...它也指向同一个地址。

这很令人困惑,我认为C FAQ 解释得很好。关于数组和指针的整章应该是所有 C 程序员的必读。


另一件值得注意的事:优化器使用一种叫做“字符串池”的东西,这意味着如果编译器在源代码中两次遇到相同的字符串文字,它将把它存储在同一个地址。因此,您的代码实际上只是将同一内存位置的内容打印了两次。要查看是否使用了字符串池,只需运行以下代码:

printf("%p\n", "Hello");
printf("%p\n", "Hello");

只要字符串相同,它就应该打印两次相同的地址。更改其中一个字符串,您将获得不同的地址。

【讨论】:

  • 这是一个很棒的答案。谢谢。
  • @alkis 如果您还没有阅读我发布的链接,请务必阅读:) 对于初学者和退伍军人来说,这都是非常好的阅读材料。
  • 我肯定会的。谢谢先生的帮助。
【解决方案3】:

"Hello"&amp;"Hello" 都返回 char 数组(字符串)的基地址。

你正在使用%s,它用于字符串变量的打印

【讨论】:

    【解决方案4】:

    这与 printf%s 上下文有关

    以下的基地址相同:

    &amp;"Hello" ==&gt; &amp;"Hello"[0] ==&gt; "Hello"+0 ==&gt; "Hello"

    【讨论】:

    • 试试:printf("%s\n", "Hello"+2); 看看我的意思
    • 我没有投反对票,但我不同意你的回答。 &"Hello" 的类型为 char (*)[6],而 &amp;"Hello"[0] 的类型为 char *。您的 ==&gt; 似乎暗示它们是等价的。
    • @cnicutar 我知道,其目的是用printf%s(基地址)告诉"String"+i 的任何行为
    猜你喜欢
    • 2013-04-09
    • 1970-01-01
    • 2018-02-19
    • 1970-01-01
    • 2015-07-03
    • 2019-06-08
    • 1970-01-01
    • 2016-07-19
    • 2016-03-24
    相关资源
    最近更新 更多