【问题标题】:NUL termination - is it always required?NUL 终止 - 是否总是需要?
【发布时间】:2020-01-17 14:59:57
【问题描述】:

我被教导总是 nul 终止字符数组。我理解在没有 nul 终止的情况下使用字符串库函数的含义。

以下代码是否被认为是不好的做法?

unsigned char foo[2] = { 0xFF, 0xFE }; // not null terminated

unsigned char bar[3] = { 0 };

memcpy(bar, foo, sizeof(foo));

假设您要连接两个字节数组。您不希望中间有空终止符。是声明foo[3],包含空终止符,并做sizeof(foo)-1更好还是上面的代码可以?

【问题讨论】:

  • “你正在连接两个字节数组。你不希望空终止符在中间。” ---> 为什么不呢? 1,2,0,4,5 的 unsigned char 数组很好。 string 是字符数组的选择数据内容。并非所有字符数组都是字符串。

标签: c nul


【解决方案1】:

不,并不总是需要 NUL 终止。

空字符'\0'是字符串所需要的,一般来说字符数组不需要。

memcpy(bar, foo, sizeof(foo)); 很好。

【讨论】:

    【解决方案2】:

    如果数组不是逻辑 C 样式字符串,并且没有与任何需要 C 样式字符串的 API 一起使用,那么您不需要 NUL 终止,就像您对数组所做的一样的int。 NUL 终止对于逻辑 C 风格的字符串是必需的,而不是所有恰好由 char 大小的值组成的数组。

    只要确定它是不是一个字符串;您不希望以后的维护人员将某些内容传递给字符串 API,因为它在逻辑上看起来类似于字符串(其中缺少 NUL 只是通过将字符串 API 替换为长度来避免 NUL 的“优化”- API)。

    【讨论】:

      【解决方案3】:

      您似乎误解了 NUL 终止的用途。在 C 中,字符串只能表示为字节序列。为了处理字符串,有两种主要方法:

      1. 始终知道它的长度,并且每次都传递它。
      2. 不知道它的长度,但使用一个唯一的终止字节(NUL 字节\0),这样任何扫描字符串的代码都可以识别何时到达末尾。

      当然,NUL 终止符的使用只适用于字符串,更准确地说,在处理期望字符串以 NUL 终止的函数时:所有标准 C 库函数都这样做。不过,人们可以很好地编写自己的库,其中包含处理非 NUL 终止字符串的函数。

      如果您正在处理通用char(或unsigned char)数组,则根本不需要用NUL 终止它们,如果您不打算将它们用作字符串。


      除了上述之外,NUL 终止符隐式添加仅用于使用字符串文字的声明,例如:

      char foo[] = "hello";
      // foo actually contains 'h' 'e' 'l' 'l' 'o' '\0'
      

      但是不是在声明char数组时:

      char foo[] = {'h', 'e', 'l', 'l', 'o'};
      // foo actually contains 'h' 'e' 'l' 'l' 'o'
      

      用小于数组大小的初始化器声明数组具有用零填充其余槽的效果,但这是另一回事:

      char foo[5] = {'h', 'i'};
      // foo actually contains 'h' 'i' '\0' '\0' '\0'
      

      在 cmets 中回答您的问题:

      缺少 NUL 终止使其他程序员有机会滥用该变量。滥用的机会是一个问题吗?我从这里的答案中收集到事实并非如此。

      并非如此,只要您使用有意义的名称,并确保在您不打算使用时,变量并不代表字符串。

      【讨论】:

      • C 标准库将 string 定义为包含 null 字符。 “非 NUL 终止的字符串”不遵循 C 规范。
      • @chux-ReinstateMonica 谁提到了 C 标准库?我没有。可以很好地实现自己的库,将字符串处理为非 NUL 终止的字符序列,传递长度。
      • OP 提到“使用字符串库函数”。
      • 我已经澄清了答案。
      • @MikeSeeds 好吧,它不是,只要你使用有意义的名称并确保变量不代表字符串,而是字节数组。
      猜你喜欢
      • 2017-05-29
      • 2013-03-08
      • 2018-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-07
      • 1970-01-01
      • 2013-08-22
      相关资源
      最近更新 更多