在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 *也表现出不同的行为。有人可以向我解释这背后的机制吗?
答案 0 :(得分:3)
如果您希望最大限度地将const
数组放入实际只读内存的机会,您应该将它们static
设为:{/ p>
static const char c[] = "abcdef";
这是因为具有自动存储持续时间的所有变量通常都在相同的内存区域中创建,无论它们是否为const
- 是否合格。因此,这个存储区域不能只读。
但是,鉴于您的实现显然没有将字符串文字放入只读内存中,它可能根本不使用只读内存,警告可能是您所希望的最佳选择。如果您使用的是基于gcc的编译器,您还可以尝试-fno-writable-strings
编译器选项。
这两行是错误的原因:
a = "overwrited";
c = "overwrited";
是因为a
和c
是数组,并且无法使用=
运算符(无论它们是否为const
)直接分配数组。变量声明中的=
不是=
运算符 - 它只是初始化语法的一部分,而数组可以进行初始化。
这些行没问题的原因:
b = "overwrited";
d = "overwrited";
是因为b
和d
是常量char
的非常量指针。这些分配不会改变b
和d
指向的原始字符串 - 它们会将b
和d
更改为指向不同的字符串(可能是相同的字符串,实际上。)
如果您希望b
和d
成为常量指针(以便指针本身无法更改),您可以更改声明:
char * const b = "abcdef";
const char * const d = "abcdef";
.. b
和d
的赋值至少应该从编译器发出错误消息。
答案 1 :(得分:1)
const char c
和const char* d
都是常量且只读的位置,您尝试分配新内容。使用编译器的警告实际上是我的错误(gcc 4.4.3)。
1)不要忽视警告。
2)修改字符串文字是未定义的行为。(幸运的是,你得到了预期的输出,但这并不意味着你被允许。)
3)提高编译器中警告和错误的严格程度。
答案 2 :(得分:-1)
<强> 1。常数强>
你可以使用指令
\#define CONST_NAME value
然后在您的代码文件中使用CONST_NAME。预处理器将使用值替换CONST_NAME的实例 另外,表示字符数组的字符串和char []与C?中的字符串的区别是什么?
<强> 2。 char *和char []
char *是指向char类型的对象的指针。没有固定的大小。 char *指向你的“字符串”的第一个字符。
char []是一个具有固定大小的char数组。
通常,管理char数组比指针更容易。但是当你不知道你的“字符串”的大小时,我们就是指针。
我建议阅读有关指针的内容。这就是C的意思:)