2
#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?

2
  • probably because the title doesn't match the question. Commented Mar 24, 2010 at 16:27
  • Fixed the title after I was misled here with a Google search Commented Mar 30, 2013 at 10:20

9 Answers 9

9

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

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

4 Comments

Arrays don't have bounds checking in applications, either.
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.
@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.
@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.
8

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.

Comments

2

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.

7 Comments

Or more specifically, it'll compile but it'll do weird things when you run it.
This doesn't answer the question, which was why this compiles in the first place, not how it behaves.
@Edan Maor: "extra initializers for fixed size arrays are discarded"
It compiles because it's perfectly legal C++ code. C++ code isn't required to work ;)
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.
|
2

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).

1 Comment

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.
1

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

Comments

0

You need 6 characters to store "hello" as a null terminated string. But char arrays are not constrained to store nul terminated string, you may need the array for another purpose and forcing an additional nul character in those cases would be pointless.

Comments

0

That is because in C memory management is done manually unlike in java and some other few languages.... The six places you allocated is not checked for during compilation but if you have to get into filing(I mean storing actually) you are going to have a runtime error becuase the program kept five places in memory(but is expected to hold six) for the characters but the compiler did not check!

Comments

-1

"hello" string is kept in read-only memory with 0 in the end. "a" points to this string, this is why the program may work correctly. But I think that generally this is undefined behavior. It is necessary to see Assembly code generated by compiler to see what happens exactly. If you want to get junk output in this situation, try:

char a[5] = {'h', 'e', 'l', 'l', 'o'}

2 Comments

@Alex Farber: I am still getting a hello as output!
It is necessary to test both in Debug and Release configurations. Again, the real answer is in Assembly code.
-1

The C compiler you are using does not check that the string literal fits to the char array. You need 6 characters in the array to fit the literal "Hello" since the literal includes a terminating zero. Modern compilers, such as Visual C++ 2010 do check these things and give you and error.

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.