为什么字符串数组的最后一个索引在C中什么都不显示?

时间:2019-01-28 22:27:04

标签: c arrays

我很好奇为什么数组29中的最后一个元素是27,而不是28?当我尝试在第28位打印对象时,为什么会有空白? s应该是第28位的最后一个对象吗?

#include <stdio.h>

int main(void) {
    char strArray[] = { "Jonsnow from Game of Thrones" };
    int lastElem = sizeof(strArray);

    printf("%s\n", strArray);
    printf("Size of array is: %d\n", sizeof(strArray));
    printf("first array value: %c \n", strArray[0]);
    printf("last array value: %c \n", strArray[lastElem - 1]);
    printf("last array value: %c \n", strArray[lastElem - 2]);

    return 0;
}

输出:

Jonsnow from Game of Thrones
Size of array is: 29
first array value: J
last array value:
last array value: s

5 个答案:

答案 0 :(得分:3)

C字符串中的最后一个字节是空终止符,即值为0的字节,也写为'\0'strArray是从C字符串常量初始化的char数组,其大小恰好是初始化程序的大小,包括空字节,因此strArray[lastElem-1]是空字节'\0'

printf %c格式输出一个空字节应该可以正常工作,将一个空字节写入stdout,但是您的终端有可能忽略这些字节并产生输出,发布。您可以尝试将程序的输出重定向到文件,然后使用十六进制编辑器检查该文件,以查看是否确实在换行符之前包含空字节。

在装有OS / X的MacBook上,我得到了相同的行为:

chqrlie@mba1 ~/dev/stackoverflow > ./nullbyte
Jonsnow from Game of Thrones
Size of array is: 29
first array value: J
last array value:
last array value: s

但这是程序输出的二进制转储:

chqrlie@mba1 ~/dev/stackoverflow > ./nullbyte | od -bc
0000000   112 157 156 163 156 157 167 040 146 162 157 155 040 107 141 155
           J   o   n   s   n   o   w       f   r   o   m       G   a   m
0000020   145 040 157 146 040 124 150 162 157 156 145 163 012 123 151 172
           e       o   f       T   h   r   o   n   e   s  \n   S   i   z
0000040   145 040 157 146 040 141 162 162 141 171 040 151 163 072 040 062
           e       o   f       a   r   r   a   y       i   s   :       2
0000060   071 012 146 151 162 163 164 040 141 162 162 141 171 040 166 141
           9  \n   f   i   r   s   t       a   r   r   a   y       v   a
0000100   154 165 145 072 040 112 040 012 154 141 163 164 040 141 162 162
           l   u   e   :       J      \n   l   a   s   t       a   r   r
0000120   141 171 040 166 141 154 165 145 072 040 000 040 012 154 141 163
           a   y       v   a   l   u   e   :      \0      \n   l   a   s
0000140   164 040 141 162 162 141 171 040 166 141 154 165 145 072 040 163
           t       a   r   r   a   y       v   a   l   u   e   :       s
0000160   040 012
              \n
0000162

如您所见,第四行的空格之间确实存在一个空字节。

还请注意,程序中存在错误:%d对于类型size_t的参数可能不合适。 C99格式为%zu,但是为了可移植到C99运行时支持不佳的系统,我建议这样做:

printf("Size of array is: %lu\n", (unsigned long)sizeof(strArray));

答案 1 :(得分:2)

lastElem-1保留给空终止符'\ 0'。

空终止符不打印任何内容,因为它是表示字符串结尾的标记,因为如果没有空终止符,仅给出一些char数组,则不清楚字符串的结尾。

答案 2 :(得分:2)

初始化带有双引号括起来的字符串字面量的char []数组时,您没有看到的是将空终止符隐式添加到字符串的末尾。这就是为什么数组长度为29的原因,尽管您的字符串文字只有28个可打印字符。

答案 3 :(得分:1)

使用字符串常量初始化char数组而不给数组大小时,数组的大小是字符串常量中的字符数,加1表示终止的空字节

因此strArray[lastElem-1]的值为0,通常将该值打印为字符不会打印任何内容。

如果您使用strlen而不是sizeof,则将获得28,而strArray[lastElem-1]将是's'

答案 4 :(得分:1)

这是因为在C字符串(一个字符数组)中,最后一个位置是一个空终止符:“ \ 0”用于结束C字符串。因此,如果您尝试打印出最后一个索引,您将不会得到结果。因此,实际String的最后一个元素就是数组的大小-2,如您从输出中看到的那样。