通常正如另一张海报所写:
char s[6] = {'s', 't', 'r', 'i', 'n', 'g'};
或者如果你当前的 C 字符集是 ASCII,这通常是正确的(今天没有多少 EBCDIC)
char s[6] = {115, 116, 114, 105, 110, 107};
还有一种在很大程度上被忽略的方式只适用于 C(不是 C++)
char s[6] = "string";
如果数组大小太小而无法容纳最后的 0(但足以容纳常量字符串的所有其他字符),则不会复制最后的 0,但它仍然是有效的 C(但无效的 C++) .
显然你也可以在运行时这样做:
char s[6];
s[0] = 's';
s[1] = 't';
s[2] = 'r';
s[3] = 'i';
s[4] = 'n';
s[5] = 'g';
或(与上述 ASCII 字符集的注释相同)
char s[6];
s[0] = 115;
s[1] = 116;
s[2] = 114;
s[3] = 105;
s[4] = 110;
s[5] = 103;
或使用 memcopy(或 memmove 或 bcopy,但在这种情况下这样做没有任何好处)。
memcpy(c, "string", 6);
或strncpy
strncpy(c, "string", 6);
应该理解的是,在 C 中没有字符串这样的东西(在 C++ 中有字符串对象,但这完全是另一回事)。所谓的字符串只是字符数组。甚至 char 的名称也具有误导性,它不是 char 而是一种数字类型。我们或许可以将其称为字节,但在过去,使用 9 位寄存器等奇怪的硬件,字节意味着 8 位。
由于 char 经常用于存储字符代码,因此 C 设计人员想到了一种比将数字存储在 char 中更简单的方法。你可以在简单的引号之间放一个字母,编译器会理解它必须将此字符代码存储在字符中。
我的意思是(例如)你不必这样做
char c = '\0';
要将代码 0 存储在 char 中,只需:
char c = 0;
由于我们经常需要处理一堆可变长度的字符,C 设计者也选择了“字符串”的约定。只需将代码 0 放在文本应该结束的地方。顺便说一句,这种字符串表示形式有一个名称“零终止字符串”,如果您在变量名称的开头看到两个字母 sz,通常意味着它的内容是一个以零结尾的字符串。
“C sz strings”根本不是一种类型,只是一个字符数组,就像一个 int 数组一样,但是字符串操作函数(strcmp、strcpy、strcat、printf 和许多其他函数)可以理解并使用 0 结尾约定。这也意味着如果你有一个非零终止的 char 数组,你不应该调用这些函数中的任何一个,因为它可能会出错(或者你必须格外小心并使用带有 n 的函数em> 名称中的字母,例如 strncpy)。
这种约定的最大问题是在很多情况下它效率低下。一个典型的例子:你想在一个以 0 结尾的字符串的末尾放一些东西。如果你保持了大小,你可以在字符串的末尾跳转,使用 sz 约定,你必须逐个字符地检查它。处理编码的 unicode 等时会出现其他类型的问题。但是在创建 C 时,这个约定非常简单,并且完美地完成了这项工作。
如今,像“string”这样的双引号之间的字母不再像过去那样是纯字符数组,而是const char *。这意味着指针指向的是一个不应该被修改的常量(如果你想修改它,你必须先复制它),这是一件好事,因为它有助于在编译时检测到许多编程错误。