字符数组初始化,第一个元素为空

Jay*_*y B 42 c++ arrays null initialization

我最近面临一行代码和四个选项:

char fullName[30] = {NULL};
Run Code Online (Sandbox Code Playgroud)
  1. A) 第一个元素被分配一个 NULL 字符。

  2. B) 数组的每个元素都被赋值为 0 ( Zeroes )

  3. C) 数组的每个元素都被赋值为 NULL

  4. D) 数组为空。

我们选择的答案是选项 C,因为虽然数组仅使用单个 初始化NULL,但 C++ 使用NULL.

然而,我们的教授不同意,说答案是A,他说:

所以第一个元素是NULL,当你显示它时,它会显示第一个元素,也就是NULL

引文完整地显示了问题;没有提供其他信息。我很好奇哪个是正确的,如果有人能解释为什么所说的答案是正确的。

Hol*_*Cat 36

这个问题定义不明确,但选项 B 似乎是最正确的答案。

结果取决于NULL定义的准确程度,这取决于编译器(更准确地说,取决于标准库实现)。如果定义为nullptr,则代码将无法编译。(我认为没有任何主要的实现会这样做,但仍然如此。)

假设NULL未定义为nullptr,则必须将其定义为具有值的整数文字0(即0、 或0L或类似的东西),这使您的代码等效于char fullName[30] = {0};

这将用零填充数组,因此选项 B 是正确答案。

通常,当您使用花括号括起来的列表初始化数组时,每个元素都会被初始化。如果您提供的初始值设定项少于元素数量,则其余元素将归零。

关于其余选项:

  • 选项 C 不清楚,因为如果代码编译,则NULL等效于0,因此选项 C 可以认为等效于选项 B。

  • 选项 A 是否有效取决于您如何解释它。如果这意味着其余元素未初始化,那么它是错误的。如果它没有指定剩余元素会发生什么,那么它就是一个有效的答案。

  • 选项 D 完全错误,因为数组不能为“空”。

  • @KonradRudolph我想作者所说的“NULL字符”是指“NUL字符”,当解释为ASCII时,它是“\0”。 (4认同)
  • 小迂腐:“NULL”不是一个*库*定义而不是一个*编译器*定义吗?我们经常使用“由编译器定义”作为“由实现定义”的转喻,但如果我们想要精确,说“取决于标准库实现”可能更正确? (3认同)
  • @Ruslan 是的,但教授显然不知道,并且同样明显混淆了 NUL 和 NULL。 (2认同)
  • @HolyBlackCat当然,但是这个术语毫无疑问是*不正确的*,而调用一个包含空字符串本身的数组“空”在最坏的情况下是不精确的。无论如何,这只是我毫无意义的迂腐。我们一致认为,这位教授的观点完全不符合事实。 (2认同)
  • @mtraceur - `(void*)0` 不是 C++ 中有效的空指针常量。从来没有。与 C 不同,没有从 `void*` 到其他指针类型的隐式转换。所以 `int *ip = (void*)0;` 是一个错误。 (2认同)

eer*_*ika 21

char fullName[30] = {NULL};
Run Code Online (Sandbox Code Playgroud)

这是永远不应该写的东西。

NULL是一个扩展为空指针常量的宏。一个字符——而不是一个指针——在这里被初始化,所以使用NULL.

碰巧一些空指针常量也是值为 0 的整数文字(例如 0 或 0L),如果NULL扩展到这样的文字,那么尽管滥用NULL. 宏扩展到的确切内容由语言实现定义。

如果NULL相反扩展为一个空指针常量,它不是整数文字,例如nullptr- 这是完全可能的 - 那么程序是格式错误的。

NULL根本不应该用 C++ 编写,即使是初始化指针。它的存在是为了与 C 向后兼容,以便更容易地将 C 程序移植到 C++。


现在,让我们假设NULL在这个特定的 C++ 实现上,它恰好扩展为整数文字。

示例中没有分配任何内容。分配是对预先存在的对象进行的操作。在这里,数组正在初始化。

数组的第一个元素用零字面量初始化。其余元素是值初始化的。两者都导致空字符。因此,整个数组将填充空字符。

一个简单而正确的写法是:

char fullName[30] = {};
Run Code Online (Sandbox Code Playgroud)

除了关于“赋值”的措辞之外,B 和 C 同样接近正确。他们没有提到值初始化,但至少结果是一样的。A 也没有错,虽然它不完整,因为它没有描述其余元素是如何初始化的。

如果将“空”解释为“不包含任何元素”,则 D 不正确,因为该数组包含 30 个元素。如果将其解释为“包含空字符串”,则 D 将是正确答案。

  • 我什至接受答案 D 是正确的:“空”不是一个精确定义的术语,但对于该术语的合理定义,该数组确实是空的,因为它在语义上表示一个空的 C 风格字符串。*唯一*明确错误的答案是 A。 (2认同)

Ast*_*ngs 10

你几乎是正确的。

教授说的不对。确实显示首先完成NULL(当使用某些方法时),但这并没有说明数组其余部分的值,无论如何都可以简单地检查。

[dcl.init/17.5]:: [..]第 i 个数组元素使用 x i进行复制初始化,每个 1 ?一世 ?k,并为每个 k < i 进行值初始化?n. [..]

然而,没有一个选项是严格正确和措辞良好的。

发生的情况是 NULL 用于初始化第一个元素,而其他元素被零初始化。最终结果实际上是选项 B。

问题是,如果在您的平台上NULL定义为类型表达式std::nullptr_t它不是,但允许),则该示例甚至无法编译

NULL 是一个指针,而不是一个数字。从历史上看,可以在一定程度上混合和匹配这两件事,但 C++ 近年来试图加强这一点,您应该避免混淆界线。

更好的方法是:

char fullName[30] = {};
Run Code Online (Sandbox Code Playgroud)

最好的方法是:

std::string fullName;
Run Code Online (Sandbox Code Playgroud)

  • 该代码甚至不能保证编译。如果“NULL”被定义为“nullptr”,它可能根本无法编译 (2认同)