【问题标题】:Is it valid to print the address of string in C在C中打印字符串的地址是否有效
【发布时间】:2013-10-02 09:09:54
【问题描述】:

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

  • 根据How to declare strings in 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");

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

【问题讨论】:

    标签: c arrays string


    【解决方案1】:

    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_addr 的定义放入 main.c 时,我得到了两次相同的值。所以是的,这是标准明确允许的优化,但 GCC 至少仅在每个模块的基础上执行此优化。

    【讨论】:

    • 到底有没有声明一个字符串变量?
    • 我认为不可能声明一个字符串变量。始终定义一个字符串变量。我说的对吗?
    • @Patil:“字符串变量”是什么意思?您可以拥有一个 char 数组或一个指向 char 的指针。这些都可以声明。如果数组包含一个空字符,并且该空值之前的所有值都是某个特定字符集中的值(或者如果 char * 指向的值也是如此),那么您可以将变量称为“字符串”。跨度>
    • @WilliamPursell:是的,明白了。谢谢。
    【解决方案2】:

    这是 C 标准特别允许的。

    6.4.5p5-6:

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

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

    【讨论】:

    • 这个问题是关于C的
    • 你能解释一下C语言吗?
    【解决方案3】:

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

    当你这样做时

    char p2[] = "String";
    

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

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

    在这种情况下,如果您打印p3&amp;"String"相同

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

    【讨论】:

      【解决方案4】:

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

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

      但是,你不能依赖这个,因为它是一个编译器优化,可能发生也可能不发生。

      【讨论】:

      • BSS 通常用于初始化为零的静态数据。常量数据通常与代码一起放在文本部分。
      猜你喜欢
      • 2010-10-21
      • 1970-01-01
      • 2015-08-06
      • 2011-09-09
      • 2013-04-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 2021-03-01
      相关资源
      最近更新 更多