繁体   English   中英

C++ 和 C 字符串变量,字符数组大小

[英]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但索引相同0n - 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 字符串处理函数( strcatstrcmpstrcpystrchr等)都假定存在该终止符; 如果终止符不存在,这些例程将无法正常运行。

字符串存储在字符类型的数组中(对于 ASCII、EBCDIC 或 UTF-8 字符串为char或对于“宽”字符串1wchar_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等。


  1. wchar_t被引入来表示 ASCII 或 EBCDIC 定义的范围之外的字符集,因此它比 `char` 类型(通常是两个 `char` 的宽度)更宽。 随着像UTF-8这样的方案的出现来表示非英语字符集,它不是那么有用,我不认为它经常使用。
  2. 在某些时候,您会听到有人说“数组只是一个指针”。 这是不正确的。 大多数情况下,数组类型的表达式会被转换(“衰减”)为指针类型的表达式,表达式的值将是数组中第一个元素的地址。 数组对象本身不是指针,也不为指针值留出任何空间。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM