-1

Apologies if this has already been answered, but I couldn't find a good way to describe it or search it, which is why the title is a bit... odd.

    int aGrade[4];
    do {
        printf("\nType the student %ds grade: ", (i + 1));
        scanf("%d", &aGrade[i]);
        i++;
   } while (i <= 4);

For some reason, the last value input is always incremented by one. If, in the loop, aGrade[4]'s value is set to 5, and I print its value to the console, it returns as 6.

I have seen this happen with for, do and while loops and I can't figure out what's happening. Thanks in advance! :)

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 6
    `aGrade[4]` is out of bounds. Valid indices are `0..3` – Eugene Sh. Aug 15 '22 at 16:13
  • There is no `aGrade[4]`. When `aGrade` is defined with `int aGrade[4];`, its elements are `aGrade[0]`, `aGrade[1]`, `aGrade[2]`, and `aGrade[3]`. When you attempt to use `aGrade[4]`, you overflow the array and mess up program execution. – Eric Postpischil Aug 15 '22 at 16:14
  • 1
    Use a `for` loop rather than `while` loop. And the condition should be `i < 4`. This is one of the most common idioms for processing arrays, learn it by heart. – Barmar Aug 15 '22 at 16:15
  • ..and 'i' is initialized to.....what? – Martin James Aug 15 '22 at 17:34

2 Answers2

4

Your program has a buffer overflow bug due to the do-while loop condition while (i <= 4).

The array aGrade[4] can store up to 4 elements, these can be accessed by aGrade[0], aGrade[1], aGrade[2] and aGrade[3].

Note how aGrade[4] isn't an option.

int aGrade[4]; 

do{ 
     printf("\nType the student %d grade: ", (i+1)); 
     scanf("%d", &aGrade[i]); i++; 
}
while (i < 4);

You could also use a for loop which in most cases looks more clear and readable:

int aGrade[4]; 

for (int i = 0; i < 4; i++) 
{ 
     printf("\nType the student %d grade: ", (i+1)); 
     scanf("%d", &aGrade[i]); 
}
programmer
  • 462
  • 1
  • 6
0

When you allocate aGrade[4] your program creates a memory block 4 x (size of an int in your system). These can be accessed using aGrade[0], aGrade[1], aGrade[2] and aGrade[3].

You can also access aGrade[4] or aGrade[100]. It is an option but not what you are trying to do here.

aGrade[0] points to a memory location where first element of your array is stored. That location can also be dereferenced as *(aGrade + 0). When you try to access *(aGrade + 4), program tries to reach the memory address next to your array.

useful link!

*(aGrade + 4) is a random memory location. You can access&modify it. It is not what you want here or anywhere if you do not want to try it expilicitly (In cases like when you want to bypass a password check which might be an advanced topic at this point for you) .

yokus
  • 145
  • 2
  • 10
  • _"You can also access aGrade[4] or aGrade[100]"_. I am not sure I understand what you are trying to convey here. Are there additional words you can add that might explain better why you offer this suggestion? (As stated, accessing these locations is simply UB, therefore does not sound like a good suggestion.) – ryyker Aug 15 '22 at 18:25