4

在 C 中创建常量字符串的好方法是什么?无法通过对其索引位置之一进行字符分配来改变的字符串。以及在初始化后的后续执行中不能被另一个字符串替换的字符串。

我在下面的代码中尝试了 char* 和 char[] 。我尝试了使用和不使用“const”关键字的方法。结果非常离奇。

以下是我的代码:

#include <stdio.h>
main() {
    char a []= "abc" "def";
    char* b = "abcdef";
    const char c [] = "abcdef";
    const char* d = "abcdef";

    a[1] = 'y';
    b[1] = 'y';
    c[1] = 'y';
    d[1] = 'y';
    printf("%s %s %s %s \n", a, b, c, d);

    a = "overwrited";
    b = "overwrited";
    c = "overwrited";
    d = "overwrited";
    printf("%s %s %s %s \n", a, b, c, d);
}

结果是在第一个printf中,所有a、b、c、d都可以变异;但是 c 和 d 出现“分配只读位置”的警告。在第二个 printf 中,a 和 c 都返回错误。但是 b 和 d 被另一个字符串平滑地替换并被“覆盖”。

我对这个结果感到非常困惑,“const”关键字似乎对进行字符串赋值没有影响;但它对索引字符突变有影响。并且 char[] 和 char* 也表现出不同的行为。有人可以向我解释这背后的机制吗?

4

3 回答 3

3

如果您希望最大化将const数组放入实际只读内存的机会,您也应该制作它们static

static const char c[] = "abcdef";

这是因为所有具有自动存储持续时间的变量通常都是在同一内存区域中创建的,无论它们是否符合条件const。因此,该内存区域不能设为只读。

但是,鉴于您的实现显然也没有将字符串文字放入只读内存,它可能根本不使用只读内存,并且警告可能是您所希望的最好的。如果您使用的是基于 gcc 的编译器,您也可以尝试-fno-writable-strings编译器选项。


这两行是错误的原因:

a = "overwrited";
c = "overwrited";

是因为aandc是数组,数组不能直接用=操作符赋值(不管是const不是)。变量声明中的=不是=运算符 - 它只是初始化语法的一部分,并且可以初始化数组。

这些行没问题的原因:

b = "overwrited";
d = "overwrited";

是因为bd是指向常量chars 的非常量指针。这些赋值不会改变bd指向的原始字符串 - 它们会改变bd指向不同的字符串(实际上可能是相同的字符串)。

如果你想bd成为常量指针(这样指针本身就不能改变),你可以改变声明:

char * const b = "abcdef";
const char * const d = "abcdef";

..以及分配给b并且d应该至少从编译器发出错误消息。

于 2013-08-06T06:05:32.570 回答
-1

const char c并且const char* d两者都是您尝试分配新内容的常量和只读位置。编译器的警告实际上是我的错误(gcc 4.4.3)。

1)不要忽视警告。

2)修改字符串文字是未定义的行为。(幸运的是你得到了预期的输出,但这并不意味着你被允许。)

3) 提高编译器中警告和错误的严格程度。

于 2013-08-06T06:04:50.897 回答
-2

1. 常数

你可以使用指令

\#define CONST_NAME  value

然后在您的代码文件中使用 CONST_NAME。预处理器会将 CONST_NAME 的实例替换为 value 另外,和 char[] 在表示字符数组或 C 中的字符串方面有什么区别?

2. char * 和 char[]

char* 是指向 char 类型对象的指针。没有固定大小。char* 指向“字符串”的第一个字符。

char[] 是一个固定大小的 char 数组。

通常,管理 char 数组比管理指针更容易。但是当你不知道你的“字符串”的大小时,我们会使用一个指针。

我建议阅读有关指针的内容。这就是 C 的意义所在:)

于 2013-08-06T05:54:23.753 回答