收录日期:2020/12/04 06:14:28 时间:2009-01-23 02:45:29 标签:c,variables,string

I am a little confused by the following C code snippets:

printf("Peter string is %d bytes\n", sizeof("Peter")); // Peter string is 6 bytes

This tells me that when C compiles a string in double quotes, it will automatically add an extra byte for the null terminator.

printf("Hello '%s'\n", "Peter");

The printf function knows when to stop reading the string "Peter" because it reaches the null terminator, so ...

char myString[2][9] = {"123456789", "123456789" };
printf("myString: %s\n", myString[0]);

Here, printf prints all 18 characters because there's no null terminators (and they wouldn't fit without taking out the 9's). Does C not add the null terminator in a variable definition?

Your string is [2][9]. Those [9] are ['1', '2', etc... '8', '9']. Because you only gave it room for 9 chars in the first array dimension, and because you used all 9, it has no room to place a '\0' character. redefine your char array:

char string[2][10] = {"123456789", "123456789"};

And it should work.

Sure it does, you just aren't leaving enough room for the '\0' byte. Making it:

char string[2][10] = { "123456789", "123456789" };

Will work as you expect (will just print 9 characters).

If you tell C that an array is a given size, C cannot make the array any larger. It would be disobeying you if it did so! Remember that not every char array contains a null terminated string. Sometimes the array (as used) is truly an array of (individual) char. The compiler doesn't know what you are doing and cannot read your mind.

This is why C allows you to initialize a char array where the null terminator won't fit but everything else will. Try your example with a string one byte longer and the compiler will complain.

Note that your example will compile but will not do what you expect, as the strings are not null terminated (unless your compiler is doing something unusual). With GCC, running your example, I see the string I should, followed by garbage.

Alterenatively, you can use:

char* myString[2] = {"123456789", "123456789" };

Like this, the initializer computes the right size for your null terminated strings.

C allows unterminated strings, C++ does not.

C allows character arrays to be initialized with string constants. It also allows a string constant initializer to contain exactly one more character than the array it initializes, i.e., the implicit terminating null character of the string may be ignored. For example:

char  name1[] =  "Harry";   // Array of 6 char

char  name2[6] = "Harry";   // Array of 6 char

char  name3[] =  { 'H', 'a', 'r', 'r', 'y', '\0' };
                            // Same as 'name1' initialization

char  name4[5] = "Harry";   // Array of 5 char, no null char

C++ also allows character arrays to be initialized with string constants, but always includes the terminating null character in the initialization. Thus the last initializer (name4) in the example above is invalid in C++.

Is there a reason why the compiler doesn't warn that there isn't enough room for the 0 byte? I get a warning if I try to add another '9' that won't fit, but it doesn't seem to care about dropping the 0 byte?

The '\0' byte isn't it's problem. Most of the time, if you have this:

char code[9] = "123456789";

The next byte will be off the edge of the variable, but will be unused memory, and will most likely be 0 (unless you malloc() and don't set the values before using them). So most of the time it works, even if it's bad for you.

If you're using gcc, you might also want to use the -Wall flag, or one of the other (million) warning flags. This might help (not sure).