15

我有 2 个问题......(我正在学习 C,这可能是愚蠢的问题。抱歉)

  • 根据如何在 C 中声明字符串和大多数书籍,他们总是说声明一个字符串,即使你通过说分配内存

    char p2[] = "String";
    

我的问题是,无论如何要声明一个字符串?

被放置在只读区域,然后复制到数组。在 C 中这样打印字符串的地址是否有效?

printf("%p\n", &"Hello There"); // I tried, it prints some address

并通过这样做

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

它正在打印相同的地址。感觉是,它应该打印不同的地址。编译器在这里做了一些优化吗?

4

4 回答 4

14

C 标准,§6.4.5 字符串文字,说:

如果它们的元素具有适当的值,则未指定这些数组是否不同。

因此,具有相同内容的两个字符串文字可能表示相同的数组,并且打印它们的地址会两次给出相同的指针值。由编译器和链接器来决定;当我将以下程序编译为两个单独的模块时...

// main.c
#include <stdio.h>

extern void print_foo_addr(void);

int main()
{
    printf("%p\n", &"foo");
    print_foo_addr();
    return 0;
}

// printfoo.c
#include <stdio.h>

void print_foo_addr()
{
    printf("%p\n", &"foo");
}

...然后我得到两个不同的指针值(Linux 上的 GCC 4.7.3),但是当我为print_foo_addrin定义时main.c,我得到了两次相同的值。所以是的,这是标准明确允许的优化,但 GCC 至少仅在每个模块的基础上执行此优化。

于 2013-09-26T12:03:45.650 回答
3

这是 C 标准特别允许的。

6.4.5p5-6:

在翻译阶段 7 中,将一个字节或值为零的代码附加到由一个或多个字符串文字产生的每个多字节字符序列。然后使用多字节字符序列来初始化一个静态存储持续时间和长度刚好足以包含该序列的数组。...

如果它们的元素具有适当的值,则未指定这些数组是否不同。

于 2013-09-26T11:59:12.323 回答
0

"Hello There"是字符串文字,它将在字符串表中可用(获得相同地址的原因"Hello There"in printf)。

当你这样做

char p2[] = "String";

将分配内存并将“字符串”复制到新创建的内存中。但

char * p3 = "String";将指向只读部分。即字符串表。

在这种情况下,如果您打印p3并且&"String"将是相同的 .

如果您打印p2&"String",将打印不同的地址。因为p2是栈地址。

于 2013-09-26T11:59:58.253 回答
0

文字字符串被放置在一个特殊的部分,它应该是只读的。此外,如果您在多个地方使用相同的字符串文字,那么编译器通常只能创建该字符串的一个实例。这就是您在此示例中看到相同地址的原因:

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

但是,您不能依赖于此,因为它是编译器优化,可能发生也可能不发生。

于 2013-09-26T12:04:07.990 回答