1

I came across these two blocks of code:

#include <stdio.h>
int main() {
  int a[10], i;
  for (i = 1; i <= 10; i++) {
    scanf("%d", &a[i]);
    printf("%d\n", a[i]);
  }
  return 0
}

When I run the first piece of code, the code runs well but it gets overridden at some point and I do not get the expected result.

However, when I run the second piece of code the program runs perfectly fine with no error.

#include <stdio.h>
int main() {
  int size;
  scanf("%d", &size);
  int a[size], i;
  for (i = 1; i <= size; i++) {
    scanf("%d", &a[i]);
    printf("%d\n", a[i]);
  }
  return 0
}

Why does the program run perfectly in the second case? Even in the second case, the subscript goes past the declared array size.

Dwayne Towell
  • 8,154
  • 4
  • 36
  • 49

3 Answers3

3

Both code snippet has array out of bound access so you see undefined behavior

for(i=1;i<=size;i++)

If you have array of size 10 then the valid index is 0-9

Once we say undefined behavior then anything might happen even a crash. When you say it is working then it is just by luck you might not be seeing a crash but still you are accessing some memory which you have not allocated

Gopi
  • 19,784
  • 4
  • 24
  • 36
  • 2
    The OP is aware of the error and asks about the difference in behaviour. – M Oehm Jan 03 '15 at 17:34
  • 3
    @MOehm Once we say undefined behavior then it is just by luck the OP will be seeing that things might be working fine – Gopi Jan 03 '15 at 17:36
1

The code in the question — both variants — exhibits 'undefined behaviour' and consequently "anything is possible". That includes "the program crashes", and "the program behaves as if the overflow is legitimate" and "the program does its utmost to wipe the machine clean of all data". Fortunately, the last option is seldom exercised by compiler writers. (See also 'Nasal Demons' in the Wikipedia article.)

The code in the question — both variants — is broken. Until the for loop is changed to the idiomatic:

for (i = 0; i < 10; i++)

the programs are simply broken, invoking undefined behaviour, and anything can happen when they're run.

If you wish, you can analyze the assembly generated for the two faulty programs if you wish (but it is better not to). My best guess as to difference in behaviour would be that the version with the constant-length array (CLA) lays out the array and index variables differently from the version with the variable-length array (VLA), so overflowing the array in the VLA version overwrites different data from overflowing the array in the CLA version.

But there's little point in investigating what happens in detail. The behaviour is undefined, and knowing what happens with one source file and one version of one compiler with one set of compilation flags on one platform won't make the code correct or reliable or portable or anything else useful. Adding a second array can alter things; changing the compiler version, using a different compiler, moving to a new platform, or changing the optimization level of the compilation — any of these can change what happens, and you have nobody to blame but yourself because the code is broken. The problem is in the code, not in what the compiler does with it.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • :So does that mean, that the compiler behaves differently in case of Constant length array and Variable Length Array? All i want to know is that, why does the code exhibit a particular behaviour when i initialize the array size in the code itself and why does it work perfectly normal when i input the array size from the user,even though my for loop starts from 1 and not 0? I know that starting a for loop for an array with 1 is an error, which the compiler does not show, but my question is why does it behave differently in the 2 cases mentioned above in my question? – Ankita Runthala Jan 05 '15 at 19:57
  • I suggest you look at the generated assembler. This code could be treated the same by the optimizer, but for the general case of VLA (a standard acronym) vs CLA (a non-standard acronym) there may well be differences. These would be more pronounced if there are multiple VLAs in a single function, with the sizes determined by parameters to the function. The starting addresses of some of the arrays cannot be fixed at compile time relative to the stack pointer, but may vary depending on the sizes of the arrays. So, the generated assembler will be different. – Jonathan Leffler Jan 05 '15 at 20:41
  • Consider: `void matrix_add_sub_print(int n, int m, int matrixA[m][n], int matrixB[m][n]) { int matrixS[m][n]; int matrixD[m][n]; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) { matrixS[i][j] = matrixA[i][j] + matrixB[i][j]; matrixD[i][j] = matrixA[i][j] - matrixB[i][j]; } print_matrix(n, m, matrixS); print_matrix(n, m, matrixD); }` (warning: untested code). The positions of the two local matrices will be different if the calls are `matrix_add_sub_print(3, 3, matrix1, matrix2);` vs `matrix_add_sub_print(100, 100, matrix3, matrix4);`. – Jonathan Leffler Jan 05 '15 at 20:47
0

@Ashalynd :The operating system is Windows 8.1 and i am using CodeBlocks. The missed semicolon is a typing mistake. @JonathanLeffler :So does that mean, that the compiler behaves differently in case of Constant length array and Variable Length Array? All i want to know is that, why does the code exhibit a particular behaviour when i initialize the array size in the code itself and why does it work perfectly normal when i input the array size from the user,even though my for loop starts from 1 and not 0? I know that starting a for loop for an array with 1 is an error, which the compiler does not show, but my question is why does it behave differently in the 2 cases mentioned above in my question?