【问题标题】:C arrays and null byteC 数组和空字节
【发布时间】:2016-08-13 21:39:34
【问题描述】:

我有一个问题想更好地理解数组和空字节在 C 中的工作原理。

假设我有一个包含 13 个单元格的 int 数组。 假设我希望单元格编号:1、2、3 和 10 具有值。其他默认的,自动获取 nullchar \0 作为值?

我对 \0 的理解是 nullbyte 总是在数组的末尾,它的作用是告诉程序数组在哪里结束。不过好像错了

我写了一个简单的程序来验证它,看起来是这样的:

int nums[13] = {1,2,3};
nums[10] = 69;
int i;
for(i=0;i<13;i++) {
    if(nums[i]=='\0') {
        printf("null char found! in position: %d\n",i);
    }
    else {
        printf("element: %d found in position: %d of int array\n",nums[i],i);
    }
}

return 0;

这是输出:

元素:1 在 int 数组的位置:0 中找到

元素:2 在 int 数组的位置:1 中找到

元素:3 在 int 数组的位置:2 中找到

找到空字符!在位:3

找到空字符!在位:4

找到空字符!在位:5

找到空字符!在位:6

找到空字符!在位:7

找到空字符!在位:8

找到空字符!在位:9

元素:69 在位置:int 数组的 10 中找到

找到空字符!在位:11

找到空字符!在位:12

| 1 | | 2 | | 3 | | \0 | | \0 | | \0 | | \0 | | \0 | | \0 | | 69 | | \0 | | \0 | | \0 |

那么为什么默认单元格设置为 \0 值?例如,而不是留空?

null char 不应该只在整个数组的末尾出现一次吗? 谢谢

【问题讨论】:

  • 静态分配的内存用 0 填充标量或 NULL (\0) 填充指针。如果将 \0 转换为标量,它将被转换为 0。没有“空”之类的东西。无论如何,您都不应该将 NULL (\0) 与 int 进行比较,请使用文字 0。
  • “我对 \0 的理解是 nullbyte 总是在数组的末尾..”是完全错误的。您混淆了常规数组和 C 字符串。
  • @Tibrogargan \0(NUL 字符)与 NULL 指针不同。 \0 是一个所有位都设置为 0 的字节,它总是比较等于 int 0。
  • @Kninnug 是的,感谢您的更正。我的意思是 NUL。 NULL 的变体太多。 null、nul、nil、NUL 等

标签: c arrays null int


【解决方案1】:

C 中没有要求 数组 在末尾需要 \0。只有 C strings 需要 NUL 终止符(通常具有 charwchar_t 或其他 character 类型)。在 C 字符串中,\0 字节也不必位于包含它的数组的末尾,但它必须位于字符串部分的末尾。在数组中的任何位置都有 0 是完全有效的。但是如果将该数组用作字符串,则标准 C 字符串函数将解释具有最低索引的 0 来表示字符串的结尾。

当您在 C 中声明一个变量 (nums) 并在其中使用初始值设定项 ({1,2,3}) 时

int nums[13] = {1,2,3};

初始化程序中未提及的所有索引(3 到 12)都将其值初始化为 0。数组中不可能有“空”单元格。所有单元格都会有一个值,这取决于程序(mer)将哪些值视为空。

【讨论】:

    【解决方案2】:

    C类型对应内存,内存没有真正的“空”概念。有些语言可以通过放置一些“空”常量(例如,Python 有 None)将所有(或几乎)都变为“空”,但 C 不允许这样做。不允许它的一个原因是它迫使你对空状态有一个特殊的通用模式,这会产生低级的影响。例如,一个字符可以取 0 到 255 之间的任何值(包括 0 到 255)。那是因为字符占用 8 位。如果您还希望在不牺牲字符的可能值的情况下获得一个空状态,则您至少需要一个位,因为其他 8 个位可以出于正当原因使用,但出于很多原因,这是不可取的。

    对于您的数组,您使用的初始化语法将每个未指定的元素设置为零。如果你写:

    char foo[4] = {1, 2, 3, 4};
    

    那么每个元素都有一个值(请注意,它最后没有空字节,因为数组最后不需要空字节 - 但是,如果您将它们用作字符串,那么它们非常应该)。如果你写:

    char foo[4] = {1, 2};
    

    元素 0 和 1 有一个指定的值,但 2 和 3 没有,并且使用这种语法 C 会假设你想让它们为零。另一方面,如果你写:

    char foo[4];
    

    您没有为任何元素分配任何值,在这种情况下,C 根本不会初始化数组。从中读取将是未定义的行为;在实践中,通常,元素将采用之前发生在其内存位置的任何值。

    【讨论】:

      【解决方案3】:

      NULL 定义为 (void*)0 - 使用通用 ptr 强制转换为零, 这等于 NUL 字符的 (\0) ascii 代码 - 0

      数组不需要以任何特殊字符/数字结尾。

      字符串确实需要以特殊字符结尾,原因很简单,它让对字符串进行操作的函数“知道”字符串在哪里结束,例如:

      char str[100] = {'h','e','l','l','o',0}; // same as {'h','e','l','l','o','\0'}
      printf("%s",str);
      

      打印: 你好

      如果字符串中的最后一个字符不是 NUL,它将在字符串之后打印 95 个垃圾字符 ("hello"),因为数组大小为 100,编译器无法知道字符串的结束位置。

      即使在大多数编译器中第 6 个单元格的零结束了字符串,您也可以只设置“hello”字符串,它们会用零填充其余单元格,所以在这两种情况下都可以。

      【讨论】:

      • NUL(空字符的名称)和NULL(空指针文字)是不同种类的动物。
      【解决方案4】:

      首先,您将 C 字符串与常规数组混淆了。对于字符串,\0 总是在 chararray 的末尾。它表示字符串的结束。例如,假设你有这个:

      char myText[] = "hello";
      

      在这种情况下,数组位置如下所示:

      我的文本 [0] = 'h'; 我的文本 [1] = 'e'; 我的文本 [2] = 'l'; 我的文本 [3] = 'l'; myText[4] = 'o'; 我的文本 [5] = '\0';

      但是,数组不会以'\0' 结尾。再举一个例子:

      int myArray[3] = {1, 2, 3};
      

      根据您的规则,由于数组必须以 '\0' 结尾,因此这不是合法声明,因为我们只给数组 3 个元素而不是 4 个元素,并且我们需要 4 个元素才能包含 '\0'。但是,这在 C 中是完全合法的声明。显然,数组中不需要 '\0' 的空间,只需在 C 字符串的末尾。

      还要注意'\0' 等价于整数,正如Kninnug 在 cmets 中指出的那样:

      \0(空字符)与空指针不同。 \0 是一个所有位都设置为 0 的字节,它总是比较等于 int 0。

      因此,在您的程序中,您同样可以检查是否:

      if(nums[i] == 0)
      

      现在,让我们证明为什么您会得到输出。

      null char 不应该只在整个数组的末尾出现一次吗?

      没有。任何其他留空的元素都将被初始化为零值。这就是为什么你看到你所拥有的输出;不是num[0]num[1]num[2]num[10] 的元素将被初始化为零。由于您正在检查 \0(也为 0),因此不包含这些元素的其他所有内容都将为 0。


      正如alk 在 cmets 中指出的那样,空字符和空指针文字是不同的。在 C 字符串的末尾,您会看到空字符 (NUL),即 '/0' 或 0。但是,空指针文字 (NULL) 不同。

      【讨论】:

      • 谁能解释投反对票以便我改进帖子?
      • NUL(空字符的名称)和NULL(空指针字面量)是不同种类的动物。
      • A C-"string" 是一个字符数组,其中至少有一个元素等于 NUL,即空字符(等于 '\0' 等于 0) .字符数组不一定是 C-“字符串”。
      • @alk 感谢您的更正。我的修改是否使帖子更准确?
      • "首先,您将 char 数组与常规数组混淆" 不,这家伙将字符串与 char 数组混淆了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-04
      • 1970-01-01
      • 2021-01-03
      相关资源
      最近更新 更多