无法创建整数数组来保存字符

标签 c arrays

我是编程新手,几周前开始学习 C。我在一本书上读到字符数组应该以 \0 结尾,但是当我创建一个没有 \0 的数组时,它可以正常工作。怎么可能。?

#include<stdio.h>
#include<string.h>
int main()
{
    char a[] = {'a','p','p','l','e'};

    printf("%d\n",strlen(a));
    printf("%s\n",a);
    return 0;
}

上面的代码输出是

5
apple

我还读到 char 是整数数据类型的子集,但是当我使用 int 数据类型创建上述数组时,它无法正常工作。

#include<stdio.h>
#include<string.h>
int main()
{
    int a[] = {'a','p','p','l','e'};

    printf("%d\n",strlen(a));
    printf("%s\n",a);
    return 0;
}

上面的代码输出是

1
a

为什么它只考虑数组的第一个元素?

最佳答案

你的问题的前半部分相当于:

I'm new to life and started to learn about road traffic a few weeks back. I have read in a book that you should wait for the green light before entering the intersection, but when I enter the intersection without waiting, it works properly. How is it possible?

换句话说,你只是运气好而已。碰巧的是,即使您构造了一个没有正确 \0 的字符数组。终止符,内存中恰好在 e 之后有一个 0 字节在apple ,所以无论如何它都有效。但它根本不能保证有效,就像它不能保证你可以继续逆着红灯过马路而最终不会被撞到一样。

继续你的第二个问题,当你读到“char 是整数数据类型的子集”时,这并不意味着你通常会在任何地方使用 char 。 ,您还可以使用int .

这是内存中的一些字符。它们每个的大小都是一字节:

char c1 = 'p', c1 = 'e', c3 = 'a', c4 = 'r';

    +---+                   +---+
c1: | p |               c2: | e |
    +---+                   +---+

    +---+                   +---+
c3: | a |               c4: | r |
    +---+                   +---+

这是内存中的一些整数。在现代机器上,每个字节的大小可能是四个字节:

int i1 = 'p', i1 = 'e', i3 = 'a', i4 = 'r';

    +---+---+---+---+       +---+---+---+---+
i1: | p             |   i2: | e             |
    +---+---+---+---+       +---+---+---+---+

    +---+---+---+---+       +---+---+---+---+
i3: | a             |   i4: | r             |
    +---+---+---+---+       +---+---+---+---+

这是一个 char 的数组,正确的空终止:

char ca[] = { 'p', 'e', 'a', 'r', '\0' };

    +---+---+---+---+---+
ca: | p | e | a | r |\0 |
    +---+---+---+---+---+

何时 printf打印此字符串,或 strlen计算它的长度,他们从开头开始,沿着字符串一次移动一个字节,直到找到 \0 .

但是这是一个 int 的数组:

int ia[] = { 'p', 'e', 'a', 'r', '\0' };

    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
ia: | p             | e             | a             | r             | \0            |
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

但我画得有点错误,因为实际上,每个 int 中的三个额外字节并不是用空格填充的,而是用零字节填充的。 (就好像我们想用前导零来表示数字 1,即 0001。)所以更准确的图片如下所示;

    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
ia: | p  \0  \0  \0 | e  \0  \0  \0 | a  \0  \0  \0 | r  \0  \0  \0 | \0  \0  \0  \0|
    +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

所以当 printfstrlen从头开始并一次一个字节地处理数组,查找终止 \0 ,他们立即找到一个,就在第一个字母之后。

这里需要考虑的重要一点是 printfstrlen被定义为对 char 的数组进行操作。由于 C 的工作方式,他们无法知道你是否作弊并传递了 int 数组。反而。他们确实采用了相同的内存并将其视为 char 的数组。 ,因此得到的结果与您的预期截然不同。

因为很容易犯这样的错误,所以如果你犯了这样的错误,好的编译器会警告你。对于您的代码,我的编译器给了我这些警告:

warning: incompatible pointer types passing 'int [5]' to parameter of type 'const char *'
warning: format specifies type 'char *' but the argument has type 'int *'

这些消息引用类型 char * ,它是指向 char 的指针,因为当您将数组传递给函数时,实际传递的是指向数组第一个元素的指针。 (但这是另一天的话题。但这与我所说的 printfstrlen “实际上采用相同的内存并将其视为”它是一个字符数组有很大关系。)

关于无法创建整数数组来保存字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52235084/

相关文章:

javascript - 通过 id 查找元素并追加到对象中

c - Printf 在下面的代码中抛出警告而不是错误

c - 无穷大计算器

c - 执行 printf 时为 nan

c - Dynamic C (Teso PC1620-PLC) 控制 LDC

java - 使用长度为零的数组

c - 获取数组的两个地址的差异(使用 & 运算符)

c - dll中访问数组的效率

c++ - 链表问题

c - C 中的静态字符数组声明