0

I've been thinking what is the difference between

    char[] = "hello world"

and

    char[20] = "hello world"

I tried to write this short code:


    #include <stdio.h>
    #include <stdlib.h>


    int main(){
        int i;
        char str[20] = "hello world";
        for( i = 0; i<20; i++){
            if(str[i]=='\n')
                printf("\nExit character newline");
            else if(str[i]=='\0')
                printf("\nNull terminated..");
            else
                printf("\nCur: %c", str[i]);
        }
        return 0;

    }

which outputs:


Cur: h
Cur: e
Cur: l
Cur: l
Cur: o
Cur:
Cur: w
Cur: o
Cur: r
Cur: l
Cur: d
Null terminated..
Null terminated..
Null terminated..
Null terminated..
Null terminated..
Null terminated..
Null terminated..
Null terminated..
Null terminated..

On the otherhand, when I do not specifically define the array size and just use

    char[] = "hello world"

It gives me this output:

Cur: h
Cur: e
Cur: l
Cur: l
Cur: o
Cur:
Cur: w
Cur: o
Cur: r
Cur: l
Cur: d
Null terminated..
Cur: 
Null terminated..
Null terminated..
Null terminated..
Cur: 
Cur:  
Cur: a
Null terminated..

I am confused of the above output. Doesnt char[] = "hello world" just end up with 12 elements with a null terminator filling in the last element? Also, if I printf char with %s, will my assumption be correct?

jdoecs420
  • 35
  • 6
  • Can you show the code you use for the `char[]` version? – CoffeeTableEspresso Jul 02 '19 at 03:26
  • 2
    Your loop is looking at 20 characters, not the length of the string. Why on earth do you think there is any relationship between `char[] = "hello world"` and the number 20? `%s` works with 0 terminated strings. If that's what you have , `printf` will work. – John3136 Jul 02 '19 at 03:45
  • @John3136 I am trying to find out and understand what could be beyond the null terminator after 'd' in hello world. I was expecting str[] would have the rest filled with null terminators as the same observed with str[20], so I just randomly put in 20 iterations. – jdoecs420 Jul 02 '19 at 05:05
  • 1
    @jdoecs420 there is nothing interesting after the array. It's just indetermined values. Accessing them results in _undefined behaviour_ (google that). – Jabberwocky Jul 02 '19 at 06:14
  • @Jabberwocky Well there could be "interesting" things there, such as other variables that are crucial to maintain sane execution path of the program, that are now overwritten. – Lundin Jul 02 '19 at 06:22
  • Possible duplicate of [How dangerous is it to access an array out of bounds?](https://stackoverflow.com/questions/15646973/how-dangerous-is-it-to-access-an-array-out-of-bounds) – 0___________ Jul 02 '19 at 07:23

4 Answers4

3

The declaration `char str[] = "hello world" reserves space for 12 characters, the last of which is zero. Unlike some other languages. however, C implementations generally make no effort to trap on out-of-bounds array accesses. Generally, attempts to read beyond the end of a string will access the contents of whatever storage happens to follow them, but unless one uses an implementation that lets one control the placement of objects (e.g. by having only one object in a translation unit, and using a linker spec to force the data for that translation unit to be placed immediately before another one), reading past the end of a string will not have predictable consequences. If one is using an aggressive optimizing compiler, it may decide that it can omit any code which would only be relevant if the program tried to access data beyond the end of the array.

supercat
  • 77,689
  • 9
  • 166
  • 211
2

So in the first one, char[20], you have space set aside for up to 20 characters, which is why its all terminated after the last character. In the second on, char[], you don't have extra space set aside. So what appears to be happening is when you pass the end of the string, you are the memory from other parts of your machine. That is why you get random characters in there.

Here is another stackover flow that goes over this more in depth

How to declare strings in C

Lucas Hendren
  • 2,786
  • 2
  • 18
  • 33
0

In c you can read and write outside the array bounds. This is of course the Undefined Behaviour. But the language allows it.

When you read the memory which is not allocated for the object you may get unpredictable values, you may also end up in the segfault

0___________
  • 60,014
  • 4
  • 34
  • 74
0

I suggest you try this program:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "hello world";
    char str2[20] = "goodbye world";
    printf("str1: size = %zd, len = %zd\n", sizeof(str1), strlen(str1));
    printf("str2: size = %zd, len = %zd\n", sizeof(str2), strlen(str2));
}

(If you have an older compiler that doesn't accept %zd, you can use "size = %d, len = %d\n", (int)sizeof(str1), (int)strlen(str1) instead.)

The compiler will give you arrays which you can think of as looking like this:

      +---+---+---+---+---+---+---+---+---+---+---+---+
str1: | h | e | l | l | o |   | w | o | r | l | d |\0 |
      +---+---+---+---+---+---+---+---+---+---+---+---+

      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
str2: | g | o | o | d | b | y | e |   | w | o | r | l | d |\0 |   |   |   |   |   |   |
      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

(Actually, although I haven't explicitly shown them all, it's guaranteed that all the "empty" cells towards the end of str2 will contain \0 also.)

In general, if you try to access memory off of the defined end of the array: (a) you're not going to find anything interesting, and (b) it's illegal to do so, although (c) a C compiler will typically not prevent you from trying.

If you really want to see what's going on, try running this loop:

for(int i = 0; i < 30; i++)
    printf("str1[%d] = '%c'\n", i, str1[i]);

You'll probably see the string "goodbye world" lurking in the memory "off the end" of str1. If you don't, try swapping the order of str1 and str2:

char str2[20] = "goodbye world";
char str1[] = "hello world";

But of course you're "breaking the rules" here, and it's also possible that you won't see the extra "goodbye" string in either case, or that your program will crash in the attempt.

One more thing. I want to go back to something you said in a comment. You said:

I am trying to find out and understand what could be beyond the null terminator after 'd' in hello world. I was expecting str[] would have the rest filled with null terminators as the same observed with str[20].

Now, in fact, str[20] has "the rest filled with null terminators" specifically because, and only because, you explicitly allocated the array with more characters than it needed. When you say str[] = "...", on the other hand, you get an array with exactly the characters it needs (including one terminating \0). When you declare str[] = "...", it doesn't even make sense to say "the rest filled with...", because there's no "rest" to fill.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103