【问题标题】:const char* vs const char[]const char* 与 const char[]
【发布时间】:2015-03-12 11:21:19
【问题描述】:

据我所知,像“Hello”这样的字符串文字

在 C 中被认为是 char*,在 C++ 中被认为是 const char*,对于这两种语言,字符串文字都存储在 只读 内存中。(如果我错了,请纠正我)

#include <stdio.h>

int main(void)
{
    const char* c1;
    const char* c2;

    {
        const char* source1 = "Hello";
        c1 = source1;

        const char source2[] = "Hi"; //isn't "Hi" in the same memory region as "Hello" ?
        c2 = source2;
    }

    printf("c1 = %s\n", c1); // prints Hello
    printf("c2 = %s\n", c2); // prints garbage

    return 0;
}

为什么 source1source2 行为不同?(使用 gcc -std=c11 -W -O3 编译)

【问题讨论】:

  • 以这种方式分配指针是不正确的!使用strcpy
  • @ForceBru 在编译时我什至没有收到任何警告
  • source2 版本临时在堆栈上创建了一个本地数组,当您打印c2 时,该数组已超出范围。如果您想在常量(“文本”)段中模拟字符串文字,请使用静态而不是自动存储。
  • 我刚刚在 gcc 版本 4.8.2 上对其进行了测试,它打印出以下 c1 = Hello c2 = Hi 也使用了 -std=c11 标志
  • 在 C++ 中,字符串文字是任何长度的 const char [] 类型。它们衰减为const char * 指针。

标签: c++ c


【解决方案1】:

在这段代码中sn-p

 {
  const char* source1 = "Hello";
  c1 = source1;

  const char source2[] = "Hi"; //isn't "Hi" in the same memory region as "Hello" ?
  c2 = source2;
 }

source2 是代码块的本地字符数组,在退出右大括号后的块后将被销毁。

对于字符文字,它具有静态存储持续时间。因此,在退出代码块后,指向字符串文字的指针将是有效的。字符串文字将与字符数组相反。

考虑到在 C 中字符串文字 "Hello" 的类型是 char [6]。也就是说,任何字符串文字的类型都是非常量字符数组。不过,您可能不会更改字符串文字。与 C 中的 C 语言相反,字符文字具有 const 字符数组的类型。

【讨论】:

  • 在没有 -O3 选项的情况下编译我得到打印:c1 = Hello c2 = Hi 所以知道我很困惑
  • @Oleg 当您尝试访问一个不存在的对象时,程序行为未定义。只是在最后一种情况下,早期为数组分配的内存还没有被覆盖。
【解决方案2】:
const char* source1 = "Hello";

source1 只是内存位置的指针,其中定义了Hello

const char source2[] = "Hi";

source2 是字符数组类型的局部变量,并且有另一个地址,即字符串文字 Hi。在第一个} 之后,source2 将被销毁,c2 将被指向某处,但不在source2 的位置,因此在c2 被销毁后取消引用c2 只是未定义的行为。

【讨论】:

  • 所以在这种情况下,“Hi”将在与“Hello”相同的内存位置创建,但“Hi”的内容将被复制到临时数组 source2 中?之后,我将丢失 source2 数组的内容,但“Hi”仍将驻留在我的只读内存区域中?
  • @Oleg 是的,所有字符串文字都在只读内存区域中,但它是实现定义的,它们是否存储不同。
  • @Oleg 未定义行为未定义。
  • 您可以通过使用 %p printf 格式修饰符查看实际的指针值:在这种情况下,第一个字符串实际上指向文本部分 0x400754,但第二个字符串指向堆栈 0x7fffaf9130c8,以及其他局部变量.
【解决方案3】:

“Hi”不是和“Hello”在同一个内存区域吗?

你(轻微地)误会了。 "Hello" 它自己是一个 表达式,它的类型是 (const) char *,但 char source2[] = "Hi"; 是一个 声明定义、声明和初始化一个char [3] 对象。看不到const char *。在函数范围内,该对象具有自动存储期限。

在您的使用中,source2 在以下} 处不再存在,并使c2 成为无效指针。后面对c2的使用是未定义的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2023-03-15
    • 2011-07-29
    • 1970-01-01
    相关资源
    最近更新 更多