0

While loop with scanf get stack overflow after 8 number typed. When less amount, everything is ok. What's the problem?

 #include <stdio.h>

main ()
{
    int x=0;
    int j;
    int a [x];

    while (scanf("%d\n", &a[x++]) == 1);

    for (j = 0; j < x; j++)
    printf ("%d element of array is \t%d\n\n", j, a[j]);

    return 0;
}

How does code in this topic work? I mean the most accepted answer.

  • 3
    `int a [x];` meant `int a [0];` `a` has no space to store the value. – BLUEPIXY Aug 05 '17 at 14:45
  • So in this way stack overflow is after 14 inputs – Урузмаг Хадонов Aug 05 '17 at 15:00
  • 1
    it is random as it is an UB. it can happen instantly or after 50zilions iterations See my answer – 0___________ Aug 05 '17 at 15:06
  • Arrays in C do not "grow" automatically. You either need to allocate a fixed size array that is big enough for the worst case input, or use dynamic memory allocation (malloc/realloc) to create a variable sized array. – user3386109 Aug 05 '17 at 15:33
  • How does code in this topic work? I mean the most accepted answer. (the link is edited in question) – Урузмаг Хадонов Aug 05 '17 at 15:37
  • You seem to be changing the question. Don't do this; post a new question if you have a new question. That said, the code you link to works presumably because `a[]` is declared to be large enough for expected input. Note that the accepted answer adds bounds-checking with: `while (i < ARRAY_SIZE && scanf("%d", &a[i]) == 1) i++;`. – ad absurdum Aug 05 '17 at 15:39

2 Answers2

3

This code causes undefined behavior:

int a [x];

Here, a[] is a variable length array, and x has been initialized to 0. In §6.7.6.2 ¶5 about array declarators of the C11 Draft Standard, can be found:

If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero.

Since x evaluates to 0 here, in violation of a "shall" outside of the constraints, this is undefined behavior: anything could happen. That anything could happen includes the possibility that the code appears to work for small array indices. But, as it is, this is not a valid C program.

Note that, even in the absence of the first problem, there is another issue. If, for example, x is instead initialized to 1, then a[] is an array of one int. In this case, the line:

while (scanf("%d\n", &a[x++]) == 1);

leads to undefined behavior, since a[x] is already an out of bounds access with x == 1 when input begins.

ad absurdum
  • 19,498
  • 5
  • 37
  • 60
-1

You are lucky - after 9. Should be instant.

int a[x] - and x is equal zero. so no storage at all.

if size has to be a variable.

int main (void)
{
    int x=0;
    int y = 10;
    int j;
    int a [y];

    while (x < y )
        read_array_item(&a[x++]);

    //for (j = 0; j < y; j++)  // or x - it does not matter
        //printf ("%d element of array is \t%d\n\n", j, a[j]);

    return 0;
}
Ilja Everilä
  • 50,538
  • 7
  • 126
  • 127
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    I might be reading this wrong, but your "or x" should really use x, I think. You declare *a* as an array of *y* int without initialization, and if x is less than y - less integers read - then you're passing those indeterminate values to printf. – Ilja Everilä Aug 05 '17 at 15:19
  • Hmm, also if there's a read failure before x == y, then the value in x - 1 is also unusable, right? – Ilja Everilä Aug 05 '17 at 15:48
  • @Ilja Everilä I do not understand your comments. My changes were only to avoid writing and reading from the unallocated memory - avoiding segfaults. So I just added check if scanf will not write anything **outside** the array. Anything else in your comment is completely not about my answer - to make it clearer I commented unrelated lines - which were just copied from the original post – 0___________ Aug 05 '17 at 16:58
  • Of course it is and was about the answer. It contained, and still does in comments, code with somewhat obvious potential pitfall, mainly the possibility of passing indeterminate values to a standard library function - if I'm not mistaken. That is something your modifications introduced and would require very little to fix from you, but if I fail to come across with what I wrote before, we're done. – Ilja Everilä Aug 05 '17 at 17:25
  • I think that you do not understand anyway. My answer **is not about quality of data in the array but bout the array itself.**. It is obvious that no one sane will read input this way. **This is not my code** - I have slightly modified to avoid out of array accesses. – 0___________ Aug 05 '17 at 17:39
  • The insidious part is that if there's a read failure in the last integer, you cannot tell. *x* will equal *y* and there's nothing to signal whether or not the last read failed, unlike with the others when x will be less than y. – Ilja Everilä Aug 05 '17 at 17:39
  • You still cant understand Answer is about **bounds of the array**. Stop commenting unrelated issues as I am not the autfor. It is OPs code and comment there – 0___________ Aug 05 '17 at 17:40
  • 1
    No, it is not. You fixed it and broke it at the same time, is how I see it. The comment is yours, so's the potentially broken bounds check in the print loop. It seems you're impervious to criticism. – Ilja Everilä Aug 05 '17 at 17:47
  • @ Ilja Everilä happy? Do you understand now why this part is not important in this case. – 0___________ Aug 05 '17 at 18:12
  • 1
    Well, no. Now it's just terrible. I hope your hissy fit function writes some default in case of error, so that the whole array is initialized. Answers should be useful to future readers as well, not just OP (and writing proper examples is useful to OP too). Broken as designed code just spreads bad habbits. If you're answering about bounds checking, why not do it properly? – Ilja Everilä Aug 06 '17 at 06:14