+ 1

[please read through the desc.] Why does this c program take more than defined outputs ?

CODE : #include <stdio.h> int main() { int marks[5], i, n, sum = 0, average; printf("Enter number of elements: "); scanf("%d", &n); for (i = 0; i < n; ++i) { printf("Enter number%d: ", i + 1); scanf("%d", &marks[i]); sum += marks[i]; } average = sum / n; printf("Average = %d", average); return 0; } OUTPUT : Output 1 : When i use input n to be in more than what is defined (say n=7 which is more than 5 , the defined no of blocks) In this case, the Average is always wrong Enter number of elements: 7 Enter number1: 11 Enter number2: 11 Enter number3: 11 Enter number4: 11 Enter number5: 11 Enter number6: 11 Enter number7: 11 Average = 3 3 can not be the average, so is this a garbage value? Output 2 : Enter number of elements: 5 Enter number1: 11 Enter number2: 11 Enter number3: 11 Enter number4: 11 Enter number5: 11 Average = 11 Its only when i input n=5 or less that the average comes out correct. This is Obvious. But my question is why does the program take input for more than the no of blocks defined, like in the case of output 1

25th Apr 2022, 4:38 PM
blueshipswims
blueshipswims - avatar
6 Answers
+ 4
Q: Why does this C program take more than defined outputs? A: Because you (unknowingly) let it happen. You allow your code to run a loop reading <n> values into an array which only has 5 free slots. Learn how to dynamically allocate memory so you can create (or simulate) an array with same amount of elements to that <n> input given. That way, you won't face this problem again. Summary: Use of memory other than what we rightly earned (by request), or allowed for, *may* cause unpredictable results and/or trigger undefined behaviour. http://www.cplusplus.com/reference/cstdlib/calloc/ http://www.cplusplus.com/reference/cstdlib/malloc/ http://www.cplusplus.com/reference/cstdlib/realloc/ http://www.cplusplus.com/reference/cstdlib/free/
25th Apr 2022, 5:44 PM
Ipang
+ 2
Yes it's a garbage value, remember C makes it the responsibility of the programer to protect the memory. In your program you allow greater then 5 at the variable of n which can cause issues of buffer overflow of your array. all int marks[5] says is please give me five congruent locations in memory that can hold integer types. The pointer *marks only goes to marks[0] and there is no symbol in memory that says stop here.
25th Apr 2022, 4:47 PM
William Owens
William Owens - avatar
+ 2
Ipang William Owens i understood the problem. tysm to both of you. Also i tried this same problem with n=6 when the array was still defined to be marks[5], but this time the average comes out correctly Enter number of elements: 6 Enter number1: 33 Enter number2: 33 Enter number3: 33 Enter number4: 33 Enter number5: 33 Enter number6: 33 Average = 33 Why is this happening?
25th Apr 2022, 6:30 PM
blueshipswims
blueshipswims - avatar
+ 2
Anirban It depends on what is in the memory next to the locations you asked for R = Requested memory [] = 1 int of mem (size may differ by system) int marks[5] == [ ][ ][ ][R][R][R][R][R][ ][ ][ ][ ] [^ marks ^] What is next to marks is unknown and when you overwrite it with an int you might get the value of the input or it may be something else. Thus your average may be correct or wrong, you cannot predict it. At worst, what is next to marks is something the program is not supposed to touch thus causing errors.
25th Apr 2022, 7:52 PM
William Owens
William Owens - avatar
+ 2
Anirban, Please don't be confused by the few incidental events where the code seems to be working fine. It's enough for us to know that an attempt to use an unreserved memory block may or may not result as we expect, we don't make assumptions based on a few seemingly working attempts.
25th Apr 2022, 10:04 PM
Ipang
0
@Anirban A union may be a good way to explain what happens with memory. So a union is shared memory. The union only request enough memory for the largest member thus only one member is normally used at one time (the last written) but lets look at this: union My_Union { char a; int x; long y; double z; }; int main(void){ union My_Union myunion; printf("%25s%25s%25s%25s\n", "char", "int", "long", "double"); myunion.a = 'c'; printf("%25c%25i%25li%25f\n", myunion.a, myunion.x, myunion.y, myunion.z); myunion.x = 5; printf("%25c%25i%25li%25f\n", myunion.a, myunion.x, myunion.y, myunion.z); myunion.y = 6; printf("%25c%25i%25li%25f\n", myunion.a, myunion.x, myunion.y, myunion.z); myunion.z = 10.0; printf("%25c%25i%25li%25f\n", myunion.a, myunion.x, myunion.y, myunion.z); return 0; } This would return the following: char int long double c 99 99 0.000000 5 5 0.000000 6 6 0.000000 0 4621819117588971520 10.000000 so like your array overwriting the memory next to it you cannot predict what the outcome will be in. Hope this didn't confuse you more though it may help.
25th Apr 2022, 9:44 PM
William Owens
William Owens - avatar