字符串字面量存储在哪里,我能修改它们吗?

11

我对C++中的字符串文字有几个疑问。

char *strPtr ="Hello" ;
char strArray[] ="Hello";

现在 strPtr 和 strArray 被认为是字符串常量。

据我理解,字符串常量存储在只读内存中,因此我们无法修改它们的值。

我们不能这样做:

strPtr[2] ='a';
and strArray[2]='a';

以上两个语句都应该是非法的。 编译器应该在这两种情况下抛出错误。

编译器将字符串文字存储在只读内存中,因此如果我们尝试修改它们,编译器会抛出错误。

此外,const数据也被视为只读。

是不是字符串字面量和const数据都被以同样的方式处理? 我可以使用const_cast从字符串字面值中删除常量性并更改其值吗?

字符串字面量存储在哪里?(程序的数据部分)

3个回答

18
现在strPtr和strArray被认为是字符串字面值。不,它们不是。字符串字面值是你在代码中看到的东西。例如,"Hello"。 strPtr是指向该字面值的指针(该字面值现在已编译进可执行文件中)。请注意,应该是const char *; 根据C标准,您不能合法地删除const并期望在使用它时定义行为。 strArray是包含字面值副本(已编译入可执行文件中)的数组。
上述两个语句都应该是非法的。编译器在这两种情况下都应该抛出错误。不,它不应该。这两个语句完全合法。由于情况不同,第一个语句是未定义的。但如果它们是指向const char的指针,则会报错。
据我所知,字符串字面值可以像其他文字和常量一样定义。然而,存在差异:
// These copy from ROM to RAM at run-time:
char myString[] = "hello";
const int myInt = 42;
float myFloats[] = { 3.1, 4.1, 5.9 };

// These copy a pointer to some data in ROM at run-time:
const char *myString2 = "hello";
const float *myFloats2 = { 3.1, 4.1, 5.9 };

char *myString3 = "hello";  // Legal, but...
myString3[0] = 'j';         // Undefined behavior!  (Most likely segfaults.)

我在这里使用ROM和RAM是泛指。如果平台只有RAM(例如大多数Nintendo DS程序),那么常量数据可能存储在RAM中。但是写入操作仍然未定义。对于普通的C++程序员来说,常量数据的位置不应该成为问题。


9
char *strPtr ="Hello" ;

定义strPtr指向字符串字面值"Hello"的char指针——该指针的有效类型为const char*。不允许通过strPtr修改指向的内容(如果尝试这样做将会调用未定义的行为)。这是对旧版C代码的向后兼容特性。在C++0x中此约定已被弃用。请参见附录C:

更改:将字符串字面值定义为常量 字符串字面值的类型从“char数组”更改为“const char数组”。[...]

原理: 这样做可以避免调用不恰当的重载函数,因为这些函数可能希望能够修改其参数。

对原有功能的影响: 更改了明确定义的功能的语义。转换的难度:简单的语法转换,因为字符串字面值可以转换为char *; (4.2)。大多数情况都由新但已弃用的标准转换处理:

char* p = "abc"; // 在C中有效,在C++中已弃用

char* q = expr ? "abc" : "de"; // 在C中有效,在C++中无效

使用范围: 有合理理由将字符串字面值视为指向可能可修改内存的指针的程序可能很少。

char strArray[] ="Hello";

strPtr的声明类型是--它是一个包含字符串Hello(包括空终止符,即6个字符)的未指定大小的字符数组。然而,初始化使其成为完整类型,其类型为包含6个字符的数组。通过strPtr进行修改是可以的。

字符串字面量存储在哪里?

实现定义。


"strPtr的声明类型是什么?你是指strArray吗?" - 4pie0

1

早期的C和C++编译器完全基于低级编码,其中更高级别的数据保护标准是不可用的,也无法强制执行。通常在C和C++中,您可以编写任何想要的代码。

如果您知道如何使用地址,甚至可以编写代码来访问和修改您的const指针。

尽管C++确实强制执行一些编译级别的保护措施,但在运行时没有保护。您肯定可以访问自己的堆栈,并使用其值来操作任何作为const指针传入的数据。

这就是为什么C#被发明的原因,其中强制执行了更高级别的标准,因为您访问的任何内容都是引用,它是一个固定的结构,管理所有数据保护规则,并且具有无法访问和修改的隐藏指针。

主要区别在于,C++只能在编译时提供保护,而C#甚至可以在运行时提供保护。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接