【问题标题】:A few questions about char pointers关于char指针的几个问题
【发布时间】:2010-06-02 19:16:49
【问题描述】:

1- 这是如何工作的:

char *ptr = "hi";

现在编译器会将这个字符串放入内存中(我猜是堆栈),并创建一个指向它的指针?这就是它的工作原理吗?

2- 另外如果是在函数中本地创建的,当函数返回时,字符串占用的内存会被释放吗?

3- 最后但同样重要的是,为什么不允许这样做:ptr[0] = 'H';

【问题讨论】:

  • 完成了,我不知道。谢谢

标签: c pointers char


【解决方案1】:

1) 字符串not(通常)在堆栈上——它通常位于直接从可执行文件中读取的初始化数据段中。然后将指针初始化为该字符串的地址。

2) 没有。

3) 因为标准说它给出了未定义的行为。考虑一下你是否有这样的事情:

int a() { char *a = "a"; printf("%s\n", a); }
int b() { char *b = "a"; *b = 'b'; }

int main() { 
    b();
    a();
    return 0;
}

现在,当您打印出a 时,您希望得到原始值(a)还是更新后的值(b)?编译器可以但不一定共享这样的静态字符串;有些还将整个区域标记为只读,因此尝试对其进行写入会产生异常。

从 C 标准的角度来看,唯一合理的答案是将其称为未定义行为。

【讨论】:

    【解决方案2】:
    1. 编译器会把字符串“hi”放在内存的某个地方(标准没有强加在哪里),你不知道在哪里,但你必须考虑到它可能放在内存的只读部分(尽管由编译器决定)。然后会创建一个指针,指向内存中这个位置的开始。

    2. 不一定会释放内存,因为在大多数情况下,此字符串将驻留在内存的数据部分(与编译指令所在的位置相同)。

    3. 这是不允许的,因为标准不保证对这种自动分配的内存块的写访问(参见 1.)。它可能适用于某些系统/平台/编译器,但标准不保证。

    【讨论】:

      【解决方案3】:
      1. 编译器会将指针放到内存中的字符串,并将字符串“hi”的地址放入指针中。字符串本身将在程序的代码图像中。

      2. 指针的内存将被释放。

      3. 因为您的代码定义的 ptr 指向代码映像中的常量。您不能写入常量。

      【讨论】:

      • 2.指针的内存将被释放,但字符串的内存不会。如果再次调用您的函数,则字符串必须来自某个地方。
      【解决方案4】:
      1. 你可以更准确、更有力地表达为:

        const char *ptr = "hi";

        不仅实际情况会在您的代码中表达,而且编译器还将捕获写入ptr 指向的内存的尝试。字符串本身是一个“静态常量”(因此不在堆栈上),指针是一个初始化为字符串地址的变量。

      2. 不,只会在堆栈上实例化指针。数据将保留在静态常量内存中(通常作为代码文本段的一部分)。大多数编译器/链接器工具链将匹配常见的字符串,例如,如果您的代码中有多个“hi”实例,它们实际上都会引用同一个实例。

      3. 这是未定义的行为。根据文本的存储方式,它可能有效,也可能无效。现代处理器/操作系统经常实施保护机制来保护代码段不被修改和执行;由于此类字符串通常也在代码段中,因此尝试修改字符串可能会导致运行时异常。最好在编译时通过声明指针const 来检测此错误。

        如果您碰巧使用的是 16 位 DOS 编译器或没有内存保护的目标,它可能会工作;但是因为我可能会整理常见的字符串,所以您可能正在修改由多个指针引用的字符串。在嵌入式目标上,字符串可能驻留在 ROM 中,在这种情况下,即使访问没有被认为是非法的,它也不会产生任何影响。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-30
        • 2021-02-28
        • 1970-01-01
        • 1970-01-01
        • 2011-05-23
        • 2014-05-13
        • 2011-12-09
        相关资源
        最近更新 更多