1

I was taught to always nul terminate char arrays. I understand the implications of using string library functions without nul termination.

Is the following piece of code considered bad practice?

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

unsigned char bar[3] = { 0 };

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

Let's say you are concatenating two byte arrays. You don't want the null terminator in the middle. Is it better to declare foo[3], include the null terminator, and do sizeof(foo)-1 or is the above code fine?

Mike Seeds
  • 400
  • 3
  • 10
  • "you are concatenating two byte arrays. You don't want the null terminator in the middle." ---> Why not? An array of `unsigned char` of `1,2,0,4,5` is fine. _string_ is a select data content of a character array. Not all character arrays are _strings_. – chux - Reinstate Monica Jan 17 '20 at 15:14

3 Answers3

5

No, NUL termination is not always required.

The null character '\0' is needed for strings, not in general for character arrays.

memcpy(bar, foo, sizeof(foo)); is fine.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
3

If the array isn't a logical C-style string, and isn't used with any APIs that expect C-style strings, then you don't need to NUL terminate, any more than you do for arrays of int. NUL termination is required for logical C-style strings, not for all arrays that just happen to be made of char-sized values.

Just be sure it's clear that it's not a string; you don't want a later maintainer to be passing something to a string API because it appears logically string-like (where the lack of NUL was just an "optimization" to avoid the NUL by replacing string APIs with length-aware APIs).

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
1

You seem to misunderstand what NUL-termination is useful for. In C, strings can only be represented as sequences of bytes. In order to work with a string, there are two main methods:

  1. Always know its length, and pass it around every time.
  2. Do not know its length, but use an unique terminator byte (the NUL byte \0), so that any code scanning the string can identify when the end is reached.

Of course, the use of the NUL terminator only applies to strings, and more precisely when dealing with functions that expect the string to be NUL terminated: all standard C library functions do. One could very well write their own library with functions that handle non-NUL-terminated strings though.

If you are dealing with generic char (or unsigned char) arrays, there is no need at all to terminate them with NUL, if you do not intend to use them as strings.


In addition to the above, the NUL terminator is implicitly added only for declarations using string literals, like:

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

But not when declaring char arrays:

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

Declaring arrays with initializers smaller than the size of the array has the effect of filling the rest of the slots with zeroes, but that's another story:

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

Answering your question in the comments:

Lack of NUL termination gives other programmers the opportunity to misuse the variable. Is the opportunity for misuse an issue? I'm gathering from the answers here that it is not.

It is not, so long as you use meaningful names and make sure it's clear that a variable does not represent a string when you do not intend it to.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • 2
    The C standard library defines a _string_ as including a _null character_. "non-NUL-terminated strings" does not follow that C specification. – chux - Reinstate Monica Jan 17 '20 at 15:07
  • @chux-ReinstateMonica who mentioned the C standard library? I did not. One could very well implement its own library handling strings as non-NUL-terminated sequences of characters passing lengths around. – Marco Bonelli Jan 17 '20 at 15:08
  • 1
    OP mentioned "using string library functions". – chux - Reinstate Monica Jan 17 '20 at 15:09
  • I've clarified the answer. – Marco Bonelli Jan 17 '20 at 15:09
  • I fully understand the purpose of NUL termination. My question is more around 'good practice'. Lack of NUL termination gives other programmers the opportunity to misuse the variable. Is the opportunity for misuse an issue? I'm gathering from the answers here that it is not. – Mike Seeds Jan 17 '20 at 15:11
  • 1
    @MikeSeeds well, it is not, as long as you use meaningful names and make sure it's clear that a variable does not represent a string, but a byte array. – Marco Bonelli Jan 17 '20 at 15:14