C 什么时候 char** 应该以 null 终止?

标签 c arrays pointers char printf

在 StackOverflow 上找不到任何解决此问题的问题。

我意识到 char* 数组不必以 NULL 结尾,但想知道您希望它在什么时候结束?

例如,在调试我的代码时,我使用了很多 printf() 来查看我的变量在代码的某个阶段是否正确。

我有一个包含 4 个 char* 的 char** 值,我将最后一个 char* 设为 NULL。 随着 NULL 终止,printfs 从 values[0] 到 values[3] 给我这个 注意:names 只是我在打印完 values 数组后立即打印的另一个数组

Testing values1[0]: %HOME/bin:%PATH
Testing values1[1]: /%HOME/include
Testing values1[2]: /%HOME/lib
Testing values1[3]: (null)
Testing names2[0]: PATH
Testing names2[1]: IDIR
Testing names2[2]: LIBDIR

我有一个 char** 和 3 个 char*,所有这些都是有效的 char*。 没有 NULL 终止,printf from values[0] to values[3] 给了我这个(名字不显示)

Testing values1[0]: %HOME/bin:%PATH
Testing values1[1]: /%HOME/include
Testing values1[2]: /%HOME/lib

我认为 printf(...., values[3]) 将是未定义的行为,例如打印垃圾值,但如上面的输出所示,包括 printf(...., values[3]) 似乎没有被执行。

最佳答案

这里有很多困惑。首先:

  • NULL 指的是一个空指针常量,您仅将其用于将指针设置为指向“无”,即无效的内存位置。
  • Null 终止,有时拼写为“nul”以免与上述混淆,表示在字符数组末尾放置一个零字符 '\0'(有时称为“nul 字符”)说明字符串结束的位置。它与 NULL 指针无关。比“空终止”更好的名称可能是零终止,因为它不那么令人困惑。

碰巧,0、NULL 和 '\0' 都给出了零值,因此它们在实践中可能被用于错误的目的,代码仍然有效。然而,你应该做的是:

  • 对整数使用 0
  • 对指针使用NULL
  • 使用 '\0' 终止字符数组,从而使其成为 C 字符串。

下一个困惑:

I have an char** values that holds 4 char*

指针不保存值。数组保存值。指针不是数组,数组也不是指针。 Pointer-to-pointer 不是数组,也不是二维数组。

尽管在某些情况下,您可以获得指向数组第一个元素的指针。

指向可变长度字符串的指针数组可以声明为:char* string_array [N];。您可以使用指向指针的指针遍历此数组,但这不是一个好主意。更好的想法是使用数组索引:string_array[i]

总的来说,很少有实际需要使用指针到指针的情况。通过函数参数返回指向已分配资源的指针是它们的正常使用。如果您发现自己在其他地方使用指针到指针,这几乎可以肯定是程序设计不当的迹象。

例如,一个非常广泛但 100% 错误使用指针到指针的特殊情况是在堆上动态分配二维数组。


when should char** be null terminated?

从来没有。如上所述,这没有任何意义。您很可能不应该使用 char** 作为开头。

然而,您可以用 NULL 结束字符指针数组,以指示数组的结尾。这是常见的做法,但不要将其与字符串的零终止混淆。

例子:

const char* str_array [] =
{
  "hello",
  "world",
  NULL
};

for(size_t i = 0; str_array[i] != NULL; i++)
{
  puts(str_array[i]);
}

关于C 什么时候 char** 应该以 null 终止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35331819/

相关文章:

c++ - 与神秘指针相关的多线程速度减慢

java - C <> Java多平台通信

c - Z3 (Haskell) 中的段错误

c - 如何在C中创建基于字母的选项

java - 无论字符大小如何生成制表符缩进数组

javascript - 将 Json 数据作为单个对象而不是一个长数组推送

c - 我声明指针的顺序在 C 中真的很重要吗? getcwd() 问题

Javascript indexOf 用于未找到数组的数组数组

c - 将指针存储到 map 中

c - 从文件中读取并使用指针将数据放入动态结构中