C ++和C-string变量,char数组大小

时间:2017-10-09 12:34:44

标签: c++ c

我在这里搜索过很多文章,并用我自己的代码对这个概念进行了自我测试。我的问题是满足自己的好奇心,也许可以帮助别人,因为我找不到特别描述这个概念的答案。我的教科书(教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?

6 个答案:

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

字符串存储字符类型数组(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,等等。

<小时/>

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

答案 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 ++数组的更多信息。