0
#include <stdio.h>

int main(void) {
    char arr[10];
    gets(arr);//let's suppose input is "abcdefgshsdfhdsfsh" 
    printf("%s",arr);//output come is same as input but the allocated arr have 10 bytes memory
                        //and can store only ten characters but how come it's possible i am getting output 
                        //more than 10 character
    return 0;
}

What is the reason behind the output? Any help would be appreciated.

Niall
  • 30,036
  • 10
  • 99
  • 142
  • 2
    character strings need `\0` at the end. What you show here is undefined behaviour. – 101010 Oct 02 '14 at 06:09
  • @40two: `gets()` terminates to data read with a '\0'`. – alk Oct 02 '14 at 06:19
  • 2
    Closing this wih reference to UB without explaining **why** this is UB does not make sense. – alk Oct 02 '14 at 06:21
  • @alk I know that, I commented on the direction that he also has to think of allocating +1 one character for `\0` in the buffer. – 101010 Oct 02 '14 at 06:25
  • 1
    C/C++ don't check the limits of memory allocation when reading or writing through a pointer; therefore you can easily overwrite or overread any memory allocation without beeing immediately generating a runtime error. However, this create the possibility of having what's called a "corruption of the memory" because this extra-space might already be allocated to or will be allocated to another object and each object might overwrite what's the other has wrote. A corrupted memory is often a hard to find bug because often it will not reveal itself immediately. – SylvainL Oct 02 '14 at 06:29
  • Sorry for the fact that someone else has closed your question as a duplicate, as this is clearly not a duplicate here. – SylvainL Oct 02 '14 at 06:33
  • Reopend to be eiter answered or else closed as duplicate to a **suiting** existing question. – alk Oct 02 '14 at 06:50
  • Hope you aren't actually going to call this C++ or even use `gets` in C++ code... – crashmstr Oct 02 '14 at 15:12

3 Answers3

2

Because gets doesn't do any kind of check while getting bytes from stdin and putting them somewhere. A simple example:

char array1[] = "12345";
char array2[] = "67890";

gets(array1);

Now, first of all you are allowed to input how many characters you want, gets won't care about it. Secondly the bytes over the size of the array in which you put them (in this case array1) will overwrite whatever they find in memory because gets will write them. In the previous example this means that if you input "abcdefghijklmnopqrts" maybe, unpredictably, it will overwrite also array2 or whatever.

The function is unsafe because it assumes consistent input. NEVER USE IT!

Safer method is fgets()

So, you want to avoid gets. fgets will always read the new-line if the buffer was big enough to hold it (which lets you know when the buffer was too small and there's more of the line waiting to be read). If you want something like fgets that won't read the new-line (losing that indication of a too-small buffer) you can use fscanf with a scan-set conversion like: "%N[^\n]", where the 'N' is replaced by the buffer size - 1.

One easy (if strange) way to remove the trailing new-line from a buffer after reading with fgets is: strtok(buffer, "\n"); This isn't how strtok is intended to be used, but I've used it this way more often than in the intended fashion (which I generally avoid).

Source: copied from my saved questions.

Niall
  • 30,036
  • 10
  • 99
  • 142
rplusg
  • 3,418
  • 6
  • 34
  • 49
0

Undefined behavior means that a program isn't following the rules of the language and that the compiler makes no promises about the resulting behavior.

So when you write past the end of an array, which is undefined behavior, the language makes no promises that it will let you know about the error. It might appear to work, it might crash. It might do one thing today and another tomorrow.

It's kind of like putting 50 pounds of stuff on a shelf that's rated to hold 20 pounds. Maybe it'll hold up, maybe it'll collapse immediately. Maybe it'll hold up until you take something off and it all comes crashing down.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 1
    The shelf analogy for undefined behaviour deserves a +1! However not explaining to the OP _how_ he has written past the end of the array (unsafe behaviour of `gets()`) cancels this out (in the interests of fairness to inspector-g and his answer). – AAT Oct 13 '14 at 14:12
-2

C strings (arrays of type char) require a terminating null byte to indicate the end of the string. When the bytes of a string are being processed by e.g. printf(), the function will stop processing these bytes when null is reached. Since you are exceeding the length of the array (and the null byte at the end has been placed beyond 10 bytes away from the start of the array in whatever memory is adjacent to the array), the function proceeds through an undefined number of bytes when printing.

inspector-g
  • 4,146
  • 2
  • 24
  • 33
  • 1
    It's not the missing `0`-terminator, which makes the code fail, as `gets()` surely takes care of adding it, but the buffer overflow, provoked by the user by inputting more than 9 characters. Btw: `NULL` is different form `0` aka `NUL` aka `null` aka `'\0'`. – alk Oct 02 '14 at 06:38
  • In the specifications of the C/C++ language, a Null pointer might be different from 0 (or more precisely from `(void *)0`). However, for the Null byte, it is always equal to `(char)0` or `'\0'` and cannot be anything else. – SylvainL Oct 02 '14 at 06:46
  • Seriously? This is getting downvoted heavily because I wrote "NULL" instead of "null"? Also notice that I was careful not to write `NULL`, instead of NULL. Everything else I wrote is correct, just perhaps less verbose than some other answers here. I have never seen this level of heavy-handed pedantry on any of my answers before. – inspector-g Oct 02 '14 at 14:56
  • @inspector-g - Perhaps the downvotes are because you just say "you are exceeding the length of the array" without explaining why (i.e. that `gets()` has no way of knowing the length of the array and cannot terminate the input when the array is full). (The `NULL` / `\0` / `null` / `0` thing which alk then brings up is a bit off-topic I think - but he did label it as a "BTW" to be fair.) – AAT Oct 06 '14 at 09:37
  • Yet there is another answer here that makes no mention of the null byte issue and/or why `printf()` continues to just plow past the end of the array when printing, and it has no downvotes whatsoever. I fail to see how it is of higher quality than my answer, and how an answer that is 90% correct but simply missing perhaps one clause is worthy of so many downvotes. – inspector-g Oct 06 '14 at 13:17