![](/img/trans.png)
[英]C++: Is “my text” a std::string, a *char or a c-string?
[英]C++ and C-string variables, char array size
我在这里搜索了很多文章,并用我自己的代码对这个概念进行了自我测试。 我的问题是为了满足我自己的好奇心,也许可以帮助其他人,因为我找不到特别描述这个概念的答案。 我的教科书(教 C++)描述了一个 C 字符串变量:
C 字符串变量是一个字符数组。 以下数组声明提供了一个 C 字符串变量“s”,能够存储具有九个或更少字符的 C 字符串值:
char s[10];
10 表示字符串中的九个字母加上空字符 '\\0' 来标记字符串的结尾。 与任何其他部分填充的数组一样,C 字符串变量使用从索引变量 0 开始到所需数量的位置。
我试图理解上述内容。 如果数组大小为 10,那么总存储大小不就是 11 吗? 即 0-10 = 11 个空格。 如果 \\0 字符占据一个空格,那么我们仍然可以存储 10 个字符,而不是像书中那样存储 9 个字符。
在我自己的测试中,我声明了一个字符数组test[4]
并将单词“cat”存储在数组中。 查看数组中的各个位置时,我可以看到每个索引处的单个字符,即:
test[0] = c
test[1] = a
test[2] = t
test[3] =
test[4] =
为什么我们在字符数组中需要 2 个额外的插槽而不是 1 个?
大小为 N 的数组的索引从 0 开始,以 N-1 结束。 它没有与指数N.元素
在您的char test[4]
示例中,该数组的索引为 0、1、2 和 3。尝试访问索引 4 将超出数组的末尾。 C 和 C++ 不会阻止您这样做,并且尝试这样做会调用未定义的行为。
您可以将数组视为一组相同类型和大小的变量,它们在内存中一个接一个地连续。
数组的索引从0
作为第一个元素到n - 1
作为最后一个元素。 因此,您只需使用索引即可访问任何元素。
尝试访问索引i >= n
或负索引i < 0
的数组将导致undefined behavior
。
字符数组需要将最后一个元素设置为NULL character \\0
。
下面是一个例子:
char c[5] = "Hello"; // Error
上面的c
有 5 个元素和\\0
所以它是 6 字节长。 所以要纠正它:
char c[6] = "Hello"; // Null character added automatically
// char c[] = "Hello";
看这个例子:
char text[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
在上面这样的初始化中,您必须添加空终止符 '\\0' 否则您将在字符串的末尾得到一个垃圾字符。
std::cout << text[0]; // H which is the first element
std::cout << text[6 - 1 - 1]; // o which is the last character in the array.
字符以外的其他类型的数组不需要添加空终止符,元素数为n
但索引相同0
到n - 1
;
int array[5] = {4, 5, 9, 22, 16}; std::cout << array[0]; // 4 std::cout << array[5 - 1]; // 16
我认为您的问题来自对如何访问内存的误解。
s[n]
指的是访问指针s
指向s
值加上内存中的 n 个块,也可以写成*(s + n)
所以基本上,声明
char s[4];
并在其中设置cat
,您将在内存中获得此布局
+---+
s: | c | s[0] also (s + 0)
+---+
| a | s[1] also (s + 1)
+---+
| t | s[2] also (s + 2)
+---+
|\0 | s[3] also (s + 3)
+---+
| ? | s[4] also (s + 4)
+---+
| ? | s[5] also (s + 5)
+---+
| ? | s[6] also (s + 6)
+---+
| ? | s[7] also (s + 7)
+---+
| ? | s[8] also (s + 8)
+---+
| ? | s[9] also (s + 9)
+---+
?
代表一个我们不确定其值的变量。
您可以访问它,有时甚至可以修改它。 但是这个行为并不清楚,可以是undefined 。
对于您的示例s[4]
可以在每次执行可执行文件时更改。
char s[10];
有从 0 到 9 的有效索引,而不是你所说的 0 到 10。
C 字符串变量是一个字符数组。
这有点误导。 AC 字符串是一个字符值序列,后跟一个 0 值终止符。 例如,字符串"Hello"
表示为序列{'H','e', 'l', 'l', 'o', 0}
。 0 终止符的存在使字符序列成为字符串。 所有 C 字符串处理函数( strcat
、 strcmp
、 strcpy
、 strchr
等)都假定存在该终止符; 如果终止符不存在,这些例程将无法正常运行。
字符串存储在字符类型的数组中(对于 ASCII、EBCDIC 或 UTF-8 字符串为char
或对于“宽”字符串1为wchar_t
)。 如果有足够的空间,可以将多个字符串存储在单个数组中。 一个 10 元素的数组可以存储一个 9 个字符的字符串,或者两个 4 个字符的字符串,或者 5 个一个字符的字符串。 请记住,要存储 N 个字符的字符串,您需要 N+1 个数组元素来说明终止符。
我试图理解上述内容。 如果数组大小为 10,那么总存储大小不就是 11 吗? 即 0-10 = 11 个空格。
总存储大小为 10,但数组元素的索引从 0 到 9。给定声明
char foo[10];
您将在内存中获得以下布局:
+---+
foo: | | foo[0]
+---+
| | foo[1]
+---+
| | foo[2]
+---+
| | foo[3]
+---+
| | foo[4]
+---+
| | foo[5]
+---+
| | foo[6]
+---+
| | foo[7]
+---+
| | foo[8]
+---+
| | foo[9]
+---+
对于任何 N 元素数组,单个元素的索引从 0 到 N-1。
请记住,在 C 中,数组下标操作a[i]
被定义为*(a + i)
- 给定起始地址a
2 ,从该地址偏移i
元素(不是字节!!!)并取消引用结果。 第一个元素存储在a
,第二个元素存储在a + 1
,第三个元素存储在a + 2
等。
wchar_t
被引入来表示 ASCII 或 EBCDIC 定义的范围之外的字符集,因此它比 `char` 类型(通常是两个 `char` 的宽度)更宽。 随着像UTF-8这样的方案的出现来表示非英语字符集,它不是那么有用,我不认为它经常使用。 char test[4]
是你的数组的定义,这意味着你的数组的大小是四,但你只能使用空格: test[0], test[1], test[2], test[3]
。
您可以访问http://www.cplusplus.com/doc/tutorial/arrays/了解有关 C++ 数组的更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.