42

I was recently faced with a line of code and four options:

char fullName[30] = {NULL};
  1. A) First element is assigned a NULL character.

  2. B) Every element of the array is assigned 0 ( Zeroes )

  3. C) Every element of the array is assigned NULL

  4. D) The array is empty.

The answer we selected was option C, as, while the array is only initialized with a single NULL, C++ populates the rest of the array with NULL.

However, our professor disagreed, stating that the answer is A, he said:

So the very first element is NULL, and when you display it, it's displaying the first element, which is NULL.

The quote shows the question in its entirety; there was no other information provided. I'm curious to which one is correct, and if someone could explain why said answer would be correct.

11
  • 9
    Options A and B aren't mutually exclusive. Formally, they are both true. Commented May 10, 2020 at 21:06
  • Related-ish Commented May 10, 2020 at 21:49
  • I think it might depend on which compiler you are using. I do remember using this kind of initialisation in the early 90s and I'm fairly sure it just set the first char to \0. These were the days when NULL was defined as '\0', or (void)0, or other things depending on the compiler. Commented May 12, 2020 at 12:31
  • 1
    @MPW You would think wrong. No element is left "unassigned". Commented May 12, 2020 at 19:44
  • 1
    @MPW All elements are initialised. Commented May 12, 2020 at 19:56

4 Answers 4

36

The question is ill-defined, but Option B seems like the most correct answer.

The result depends on how exactly NULL is defined, which depends on the compiler (more precisely, on the standard library implementation). If it's defined as nullptr, the code will not compile. (I don't think any major implementation does that, but still.)

Assuming NULL is not defined as nullptr, then it must be defined as an integer literal with value 0 (which is 0, or 0L, or something similar), which makes your code equivalent to char fullName[30] = {0};.

This fills the array with zeroes, so Option B is the right answer.

In general, when you initialize an array with a brace-enclosed list, every element is initialized with something. If you provide fewer initializers than the number of elements, the remaining elements are zeroed.

Regarding the remaining options:

  • Option C is unclear, because if the code compiles, then NULL is equivalent to 0, so option C can be considered equivalent to Option B.

  • Option A can be valid depending on how you interpret it. If it means than the remaining elements are uninitialized, then it's wrong. If it doesn't specify what happens to the remaining elements, then it's a valid answer.

  • Option D is outright wrong, because arrays can't be "empty".

Sign up to request clarification or add additional context in comments.

11 Comments

@KonradRudolph I suppose by "NULL character" the author meant "NUL character", which '\0' is when interpreted as ASCII.
@Ruslan Yeah but the professor clearly isn’t aware, and equally clearly confuses NUL and NULL.
@HolyBlackCat Sure, but that terminology is unambiguously incorrect, whereas calling an array that holds an empty string itself “empty” is at worst imprecise. Anyway, this is all just pointless pedantry on my part. We can agree that the professor is wide off the mark.
Minor pedantry: isn't NULL a library definition rather than a compiler one? We often use "defined by the compiler" as metonymy for "defined by the implementation" but if we want to be precise it's probably more correct to say "depends on the standard library implementation"?
@mtraceur -- (void*)0 is not a valid null pointer constant in C++. Never has been. Unlike C, there is no implicit conversion from void* to other pointer types. So int *ip = (void*)0; is an error.
|
21
char fullName[30] = {NULL};

This is something that should never be written.

NULL is a macro that expands to a null pointer constant. A character - not a pointer - is being initialised here, so it makes no sense to use NULL.

It just so happens that some null pointer constants are also integer literals with value 0 (i.e. 0 or 0L for example), and if NULL expands to such literal, then the shown program is technically well-formed despite the abuse of NULL. What the macro expands to exactly is defined by the language implementation.

If NULLinstead expands to a null pointer constant that is not an integer literal such as nullptr - which is entirely possible - then the program is ill-formed.

NULL shouldn't be written in C++ at all, even to initialise pointers. It exists for backwards compatibility with C to make it easier to port C programs to C++.


Now, let us assume that NULL happens to expand to an integer literal on this particular implementation of C++.

Nothing in the example is assigned. Assignment is something that is done to pre-existing object. Here, and array is being initialised.

The first element of the array is initialised with the zero literal. The rest of the elements are value initialised. Both result in the null character. As such, the entire array will be filled with null characters.

A simple and correct way to write the same is:

char fullName[30] = {};

B and C are equally close to being correct, except for wording regarding "assignment". They fail to mention value initialisation, but at least the outcome is the same. A is not wrong either, although it is not as complete because it fails to describe how the rest of the elements are initialised.

If "empty" is interpreted as "contains no elements", then D is incorrect because the array contains 30 elements. If it is interpreted as "contains the empty string", then D would be a correct answer.

10 Comments

I’d even accept answer D as correct: “empty” isn’t a precisely defined term, but for a reasonable definition of the term, the array is indeed empty, since it semantically represents an empty C-style string. The only answer that is unambiguously wrong is A.
@KonradRudolph Personally, I understand "empty" as "contains no elements". An array with 30 elements would therefore not be empty. I guess there can be other interpretations then.
I mean, your interpretation clearly isn’t unreasonable, and was probably intended here. My point was mostly that, ironically, the professor’s preferred answer is the least correct.
@KonradRudolph With very small, and possibly subtle change to wording of the question, D would be unambiguously correct though: The array does contain the empty null terminated string.
+1. About "empty", for a fixed-sized array, I understand it to mean "containing undefined values". For a dynamic array, it would refer to having a length of zero, but this is not a dynamic array. You can see other examples of this usage in the wild e.g. with numpy.empty(...).
|
10

You are almost correct.

The professor is incorrect. It is true that display finishes at the first NULL (when some approaches are used), but that says nothing about the values of the remainder of the array, which could be trivially examined regardless.

[dcl.init/17.5]:: [..] the ith array element is copy-initialized with xi for each 1 ≤ i ≤ k, and value-initialized for each k < i ≤ n. [..]

However, none of the options is strictly correct and well-worded.

What happens is that NULL is used to initialise the first element, and the other elements are zero-initialised. The end result is effectively Option B.

Thing is, if NULL were defined as an expression of type std::nullptr_t on your platform (which it isn't, but it is permitted to be), the example won't even compile!

NULL is a pointer, not a number. Historically it has been possible to mix and match the two things to some degree, but C++ has tried to tighten that up in recent years, and you should avoid blurring the line.

A better approach is:

char fullName[30] = {};

And the best approach is:

std::string fullName;

5 Comments

This code is not even guaranteed to compile. It may simply not compile if NULL is defined as nullptr
@Ayxan (or any other std::nullptr_t)
“reasoning from observation, which is not a scientifically valid approach.” is epistemologically controversial, to put it politely. Reasoning from observation is in general totally valid and even required, as long as some caveats are observed.
@KonradRudolph There's a better term that I've forgotten. Will look for it in a bit
@KonradRudolph Meh, maybe it's not a fallacy. Changed my wording a bit.
0

Apparently, Your Professor is right, let's see how

char someName[6] = "SAAD";

how the string name is represented in memory:

0 1 2 3 4 5

S A A D

Array-based C string

The individual characters that make up the string are stored in the elements of the array. The string is terminated by a null character. Array elements after the null character are not part of the string, and their contents are irrelevant.

A "null string" is a string with a null character as its first character:

0 1 2 3 4 5

/0

Null C string

The length of a null string is 0.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.