我<!>#8217;我们得到了以下代码:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    cout << a << ", " << b << endl;
    return 0;
}

这编译和工作,即。打印bar, bar。现在我想证明这里发生的事情不是复制字符串。我想更改b并显示a也会更改。我想出了这个简单的代码:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    b[1] = 'u'; // ← just this line added
    cout << a << ", " << b << endl;
    return 0;
}

<!>#8230;但它是段错误。为什么?有趣的是,以下修改运行得很好:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char b[] = "bar"; // ← declaration changed here
    a = b;
    b[1] = 'u';
    cout << a << ", " << b << endl;
    return 0;
}

为什么<!>#8217;它像前一个一样发生了错误?我想我错过了指针式和数组式字符串初始化之间的一些重要区别。

有帮助吗?

解决方案

您无法更改字符串常量,这是您在第一个代码示例中使用指向文字的语法时所获得的。

另请参阅此问题:是字符串文字在静态内存中创建的c ++中?

其他提示

当你这样写:

char *b = "bar";

编译器分配一个匿名(无名)内存区域来存储字符串文字<!> quot; bar <!> quot;。字符串文字可能不会被修改,因此编译器(在链接器和操作系统的帮助下)将字符串文字放在正在运行的程序的写保护内存空间的一部分中。当您尝试修改它时,操作系统会捕获它并导致程序出现分段错误。

(你的代码是C ++,而不是C,但这与这个问题无关。)

当你写:

char *foo = "bar";

实际发生的是<!>“; bar <!>”;存储在只读的内存段中。因此,它是不可改变的。您会因为尝试修改只读段而遇到段错误。

您还可以通过打印指针的值来显示“a”已被更改。

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;

    cout << (void*)a << ", " << (void*)b << endl;
}

这将打印'a'和'b'指向的地址。
您必须转换为'void *',因为运算符<!> lt; <!> lt;为'char *'重载以打印出字符串,任何其他指针都会打印地址。

理论上,字符串文字不能分配给char *,只能分配给'const char *'。然后编译器会在你编写段错误代码之前阻止你。

这种差异可能是特定于编译器的。为了演示你的观点,使用malloc来分配缓冲区,然后将字符串复制到这个缓冲区中,当你不再需要字符串时不要忘记使用free。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top