g4ur4v
g4ur4v

Reputation: 3288

Null termination of char array

Consider following case:

#include<stdio.h>
int main()
{
    char A[5];
    scanf("%s",A);
    printf("%s",A);
}

My question is if char A[5] contains only two characters. Say "ab", then A[0]='a', A[1]='b' and A[2]='\0'. But if the input is say, "abcde" then where is '\0' in that case. Will A[5] contain '\0'? If yes, why? sizeof(A) will always return 5 as answer. Then when the array is full, is there an extra byte reserved for '\0' which sizeof() doesn't count?

Upvotes: 47

Views: 124683

Answers (8)

user8397625
user8397625

Reputation: 1

\0 is an terminator operator which terminates itself when array is full if array is not full then \0 will be at the end of the array when you enter a string it will read from the end of the array

Upvotes: -3

faiza najam
faiza najam

Reputation: 19

the null character is used for the termination of array. it is at the end of the array and shows that the array is end at that point. the array automatically make last character as null character so that the compiler can easily understand that the array is ended.

Upvotes: 0

Doug
Doug

Reputation: 3863

character arrays in c are merely pointers to blocks of memory. If you tell the compiler to reserve 5 bytes for characters, it does. If you try to put more then 5 bytes in there, it will just overwrite the memory past the 5 bytes you reserved.

That is why c can have serious security implementations. You have to know that you are only going to write 4 characters + a \0. C will let you overwrite memory until the program crashes.

Please don't think of char foo[5] as a string. Think of it as a spot to put 5 bytes. You can store 5 characters in there without a null, but you have to remember you need to do a memcpy(otherCharArray, foo, 5) and not use strcpy. You also have to know that the otherCharArray has enough space for those 5 bytes.

Upvotes: 5

John Kugelman
John Kugelman

Reputation: 361555

If you type more than four characters then the extra characters and the null terminator will be written outside the end of the array, overwriting memory not belonging to the array. This is a buffer overflow.

C does not prevent you from clobbering memory you don't own. This results in undefined behavior. Your program could do anything—it could crash, it could silently trash other variables and cause confusing behavior, it could be harmless, or anything else. Notice that there's no guarantee that your program will either work reliably or crash reliably. You can't even depend on it crashing immediately.

This is a great example of why scanf("%s") is dangerous and should never be used. It doesn't know about the size of your array which means there is no way to use it safely. Instead, avoid scanf and use something safer, like fgets():

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.

Example:

if (fgets(A, sizeof A, stdin) == NULL) {
    /* error reading input */
}

Annoyingly, fgets() will leave a trailing newline character ('\n') at the end of the array. So you may also want code to remove it.

size_t length = strlen(A);
if (A[length - 1] == '\n') {
    A[length - 1] = '\0';
}

Ugh. A simple (but broken) scanf("%s") has turned into a 7 line monstrosity. And that's the second lesson of the day: C is not good at I/O and string handling. It can be done, and it can be done safely, but C will kick and scream the whole time.

Upvotes: 68

Praetorian
Praetorian

Reputation: 109089

Any string greater than 4 characters in length will cause scanf to write beyond the bounds of the array. The resulting behavior is undefined and, if you're lucky, will cause your program to crash.

If you're wondering why scanf doesn't stop writing strings that are too long to be stored in the array A, it's because there's no way for scanf to know sizeof(A) is 5. When you pass an array as the parameter to a C function, the array decays to a pointer pointing to the first element in the array. So, there's no way to query the size of the array within the function.

In order to limit the number of characters read into the array use

scanf("%4s", A);

Upvotes: 4

harpun
harpun

Reputation: 4110

As already pointed out - you have to define/allocate an array of length N + 1 in order to store N chars correctly. It is possible to limit the amount of characters read by scanf. In your example it would be:

scanf("%4s", A);

in order to read max. 4 chars from stdin.

Upvotes: 13

Kiril Kirov
Kiril Kirov

Reputation: 38143

You'll end up with undefined behaviour.

As you say, the size of A will always be 5, so if you read 5 or more chars, scanf will try to write to a memory, that it's not supposed to modify.

And no, there's no reserved space/char for the \0 symbol.

Upvotes: 4

RC.
RC.

Reputation: 28197

There isn't a character that is reserved, so you must be careful not to fill the entire array to the point it can't be null terminated. Char functions rely on the null terminator, and you will get disastrous results from them if you find yourself in the situation you describe.

Much C code that you'll see will use the 'n' derivatives of functions such as strncpy. From that man page you can read:

The strcpy() and strncpy() functions return s1. The stpcpy() and stpncpy() functions return a pointer to the terminating `\0' character of s1. If stpncpy() does not terminate s1 with a NUL character, it instead returns a pointer to s1[n] (which does not necessarily refer to a valid mem- ory location.)

strlen also relies on the null character to determine the length of a character buffer. If and when you're missing that character, you will get incorrect results.

Upvotes: 3

Related Questions