storing of strings in char arrays in C

18,525

Solution 1

The C compiler will let you run off the end of arrays, it does no checks of that sort.

Solution 2

The C compiler allows you to explicitly ask for no null terminator.

char a[] = "Hello";  /* adds a terminator implicitly */
char a[6] = "Hello"; /* adds a terminator implicitly */
char a[5] = "Hello"; /* skips it */

Any value smaller than 5 results in an error.

As for why - one possibility is that your strings are of a fixed size, or are being used as buffers of byte values. In these cases you do not need a null terminator.

Best practice is to use char a[] so the compiler can set it to the correct value (including terminator) automatically.

Solution 3

a doesn't contain a null terminated string (extra initializers for fixed size arrays - such as the null terminator in "hello" - are discarded), so the behaviour when a pointer to that array is passed to puts is undefined.

Solution 4

In my experience, a lot of compilers will let you get away with compiling this. It will usually crash at runtime, though (because you don't have a null terminator).

Solution 5

C char array initialization includes the terminating null only if there is room or if the array dimensions are not specified.

Share:
18,525
Lazer
Author by

Lazer

Updated on June 11, 2022

Comments

  • Lazer
    Lazer almost 2 years
    #include<stdio.h>
    int main()
    {
      char a[5]="hello";
      puts(a);  //prints hello
    }
    

    Why does the code compile correctly? We need six places to store "hello", correct?

  • Brendan Long
    Brendan Long about 14 years
    Or more specifically, it'll compile but it'll do weird things when you run it.
  • Newbie
    Newbie about 14 years
    This doesn't answer the question, which was why this compiles in the first place, not how it behaves.
  • CB Bailey
    CB Bailey about 14 years
    @Edan Maor: "extra initializers for fixed size arrays are discarded"
  • Brendan Long
    Brendan Long about 14 years
    It compiles because it's perfectly legal C++ code. C++ code isn't required to work ;)
  • Brian
    Brian about 14 years
    Arrays don't have bounds checking in applications, either.
  • CB Bailey
    CB Bailey about 14 years
    I think I've explained the error; the error is passing a parameter than isn't a null-terminated string to puts. The initialization of the char array is valid, even if dubious.
  • Newbie
    Newbie about 14 years
    @Charles: OK you're right, but maybe you could emphasize that (and maybe explain why C lets you get away with this particular thing: is it ever not a bug?)
  • Kjir
    Kjir about 14 years
    It will crash only if puts() ends up reading memory not owned by the program, but it may not crash if the memory beyond the array does contain a null character. This is important to understand because problems like this could lead to segmentation faults that don't happen every time the program is run.
  • Pavel Minaev
    Pavel Minaev about 14 years
    It does work just fine, too. It's not illegal to have a non-null-terminated char array in C++. You shouldn't treat it as string (which is, by convention, a null-terminated char array), but that's an altogether different story.
  • Pavel Minaev
    Pavel Minaev about 14 years
    As a general statement, this is incorrect, because the C Standard does permit compilers to insert checks as they see fit (what happens is undefined behavior, but that doesn't mean that a particular compiler cannot define it); and, indeed, some compilers do insert array bound checks, depending on compilation flags etc.
  • Lazer
    Lazer about 14 years
    @Alex Farber: I am still getting a hello as output!
  • Pavel Minaev
    Pavel Minaev about 14 years
    @eSKay, same thing as above applies. They usually don't, but your particular C++ compiler may have an option to insert them, with implementation-defined effect if they fail.
  • Alex F
    Alex F about 14 years
    It is necessary to test both in Debug and Release configurations. Again, the real answer is in Assembly code.
  • Brian
    Brian about 14 years
    @Pavel: I recall a presentation I went to on designing a crash-resistant C/C++ compiler for when not crashing was a must. It did fun stuff like handling memory leaks by overwriting existing memory in the code and using modulo operations on array indexes instead of bounds checking. When testing the compiler on existing programs with crash bugs, they found it mostly worked.