我在这里搜索过很多文章,并用我自己的代码对这个概念进行了自我测试。我的问题是满足自己的好奇心,也许可以帮助别人,因为我找不到特别描述这个概念的答案。我的教科书(教C ++)描述了一个C字符串变量:
C字符串变量是一个字符数组。以下数组声明提供了一个C字符串变量" s"能存储一个 包含九个或更少字符的C字符串值:
char s[10];
10表示字符串中的9个字母加上空字符' \ 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?
答案 0 :(得分:5)
大小为N的数组的索引从0开始,以N-1结尾。它不具有索引为N的元素。
使用char test[4]
的示例,数组具有索引0,1,2和3.尝试访问索引4将脱离数组的末尾。 C和C ++不会阻止您这样做,并且尝试这样做会调用undefined behavior。
答案 1 :(得分:1)
您可以将数组视为一组相同类型和大小的变量,这些变量在内存中是连续的,并且紧挨着另一个。
数组从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'};
在这样的初始化中,您必须添加空终结符字符&#39; \ 0&#39;否则你会在字符串的末尾得到一个垃圾字符。
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
答案 2 :(得分:1)
我认为你的问题来自对你如何访问内存的误解。
s[n]
指的是访问指针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]
每次执行可执行文件时都可以更改。
答案 3 :(得分:0)
char s[10];
的有效索引从0到9而不是0到10。
答案 4 :(得分:0)
C字符串变量是一个字符数组。
这有点误导。 C字符串是一系列字符值,后跟一个0值终止符。例如,字符串"Hello"
表示为序列{'H','e', 'l', 'l', 'o', 0}
。 0终止符的存在使字符序列成为 string 。所有C字符串处理函数(strcat
,strcmp
,strcpy
,strchr
等)都假定存在该终结符;如果终止符不在那里,那些例程将无法正常运行。
字符串存储字符类型数组(char
用于ASCII,EBCDIC或UTF-8字符串,或wchar_t
用于&#34;宽&#34;字符串 1 )。如果有足够的空间,则可以将多个字符串存储在单个阵列中。 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`s的宽度)更宽。随着像UTF-8这样的方案的出现来代表非英语字符集,它并没有那么有用,我也不会经常使用它。
答案 5 :(得分:0)
<input type="radio" name="question1" value=1> Choose me <br/>
<input type="radio" name="question1" value=2> Or me! <br/>
<p id="demo"></p>
是数组的定义,它表示数组的大小为4,但您只能使用空格:char test[4]
。
您可以访问http://www.cplusplus.com/doc/tutorial/arrays/以了解有关c ++数组的更多信息。