14

Probably I'm just too dump for googling, but I always thought char arrays get only null terminated by an literal initialization (char x[]="asdf";) and got a bit surprised when I saw that this seems not to be the case.

int main()
{
    char x[2];
    printf("%d", x[2]);
    return 0;
}

Output: 0

Shouldn't an array declared as size=2*char actually get the size of 2 chars? Or am I doing something wrong here? I mean it isn't uncommon to use a char array as a simple char array and not as a string, or is it?

user1329846
  • 171
  • 1
  • 1
  • 7

3 Answers3

28

You are accessing an uninitialized array outside its bounds. That's double undefined behavior, anything could happen, even getting 0 as output.

In answer to your real question: Only string literals get null-terminated, and that means that char x[]="asdf" is an array of 5 elements.

K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • I've thought about that too, so I tried to make arrays with different sizes and the array was always followed by a 0. (the 0 shown in my sample wasn't followed by a 0, but an array with size 3*char at the same location was) – user1329846 Jun 27 '12 at 15:19
  • 1
    @user1329846: Whatever is stored in memory after the array ends is up to the compiler, you are getting 0s but could as well get any other number as the standard says if you try to read that location all bets are off. Let me make this clear: even if you were lucky to always get 0s there, your code still triggers _undefined behavior_ and may fail at any time. – K-ballo Jun 27 '12 at 15:26
  • 1
    Thank you for not using `anything can happen, even your computer could set itself on fire`. No, it can't. And all those grandiose examples are just stupid. – jn1kk Jun 27 '12 at 15:28
  • @skynorth: An example that may seem stupid yet it _may_ happen is that the compiler decides to output an empty executable, as it can presume the line triggering _undefined behavior_ will never be called in a _defined_ context. – K-ballo Jun 27 '12 at 15:39
  • Ok, thanks for your help. So I'll have to accept that this is all a series of strange coincidence or I'm owner of a strange overmuch working garbage collector... O.o – user1329846 Jun 27 '12 at 16:23
  • 3
    @skynorth: they're not stupid, just simplified for dramatic effect. The correct version is, "anything is permitted to happen by the standard -- the implementation is permitted to to set the computer on fire". The humorous version simply ignores that there are constraints on the computer's behavior other than the C standard -- OS, hardware, fire safety regulations, laws of physics, etc. – Steve Jessop Jun 27 '12 at 17:21
  • @SteveJessop : if you want drama, you should have majored in Theater in college. – jn1kk Jun 27 '12 at 17:38
  • @skynorth: I'm a veritable Renaissance man. "This is wondrous strange // And therefore as a stranger give it welcome". – Steve Jessop Jun 27 '12 at 17:40
  • 1
    @skynorth: For some people, the fact that something works seems to imply that its standard and correct code. Telling them that it may break tomorrow does not cause any effect since all they care is that it works right now. "It may set your computer on fire", on the other hand, has a way of making them stop and think twice. Maybe they should have majored in _Theater_ instead of _Computer Sciences_ though... – K-ballo Jun 27 '12 at 17:42
  • 1
    @K-ballo, that is now just a matter of following directions. If my coworkers or boss had to tell me, each time, that my computer could catch fire if I did something against their recommendation (something wrong), I would probably not have a job for long. Maybe they should have majored in Theater since it seems they are not cut out for programming (a field where following established knowledge is everything - and occasional innovation). Not my job to judge though. – jn1kk Jun 27 '12 at 17:45
5

char arrays are not automatically NULL terminated, only string literals, e.g. char *myArr = "string literal";, and some string char pointers returned from stdlib string methods.

C does no bounds checking. So an array declared as size 2*char gives you 2 memory slots that you can use, but you have the freedom to walk all over the memory on either side of that, reading and writing and thereby invoking undefined behavior. You may see 0 bytes there. You may write to array[-1] and crash your program. It is your responsibility to keep track of the size of your array and avoid touching memory that you didn't allocate.

It is common to use a char array as a simple char array, i.e. other than a C string, for instance, to hold any arbitrary buffer of raw bytes.

pb2q
  • 58,613
  • 19
  • 146
  • 147
1

If t is an array of size 2, then the last case is t[2 - 1] = t[1] and not 2. t[2] is out of bounds.

md5
  • 23,373
  • 3
  • 44
  • 93