-3

I've been tasked to code a program that processes a simple 1D array to return its element values, but the compiler has been behaving strangely; outputting more values than I have array elements.. It's also not being fully compliant with one of my statements (one that prints a new line character every 8 elements) and not assigning the largest value to my variable. I think that the other two problems will go away once the first problem is fixed, however.

Here is my brief:

Design, code and test a program that:

  1. Fills a 20 element array (marks) with random numbers between 0 and 100.
  2. Prints the numbers out 8 to a line
  3. Prints out the biggest number, the smallest number and the average of the numbers

And here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){

    srand(time(NULL));

    int marks[20];
    int i = 0;
    int sum = 0;
    int min;
    int max;

    for(i;i<=sizeof(marks);i ++){

        marks[i] = rand() % 100;
        sum += marks[i];

        if(i % 8 == 0){
            printf("\n");
        }

        printf("%d ", marks[i]);
        if(marks[i]>max){
            max = marks[i];
        }
        else  if(marks[i]<min){
            min = marks[i];
        }
    }


    printf("\n\nThe minimum value is: %d", min);
    printf("\nThe maximum value is: %d", max);
    printf("\n\nThe average value is: %d", sum / sizeof(marks));

    return 0;
}

Please can someone help me get the correct output?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
FGibbons
  • 19
  • 2
  • 1
    Fix the `for` loop condition: `i<=sizeof(marks)` is wrong, for multiple reasons: because `sizeof(int) > 1`, and because it should be `<` instead of less or equal. – kfx Jan 07 '16 at 16:38
  • A compiler does not output any "array elements". And it is very likely your statments not being compliant with the compiler (and the C standard), not vice versa. – too honest for this site Jan 07 '16 at 16:39

3 Answers3

1

sizeof() function returns the byte length of the array, so this code "thinks" your array is 20 * whatever byte size ints are on your machine. You will want to just use i < 20 in the loop or go

for (i;i<sizeof(marks)/sizeof(int); i ++) { ...

Note that you probably do not want the <= operator in the for loop, since arrays are 0 indexed, thus marks[20] is actually one beyond the array.

ggallo
  • 348
  • 1
  • 11
1

There are two problem I can see that will invoke undefined behavior in your code.

  1. By saying for(i;i<=sizeof(marks);i ++), you're out of bounds.
  2. int min; int max; are not initialized and you're attempting to use it.

to solve this.

  1. Change the for loop condition to for(i; i< 20; i++). Better to use a preprocessor construct like #define SIZ 20 and then make use of it accross your code to make it consistent and robust.
  2. Initialize your local variables. max should be INT_MIN, and min can be INT_MAX. (see limits.h for reference).

To clarify more on point 2, max and min are automatic local variables, and in case not initialized explicitly, it contains indeterminate values.

C11, chapter §6.7.9,

If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.

and then, directly from the Aneex J, §J.2, Undefined behaviour,

The value of an object with automatic storage duration is used while it is indeterminate.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Hmm, ... I really wonder if using uninitialised variables actually is UB. Actually I should know, but I'd appreciate if you provide a reference. – too honest for this site Jan 07 '16 at 16:42
  • @Olaf Sure..let me just grab the reference for you. Thanks for asking. :) – Sourav Ghosh Jan 07 '16 at 16:43
  • Please don't use magic numbers in code. Either add a `#define` or go with `sizeof` (hint: I macro to calculate array length often comes in handy). – too honest for this site Jan 07 '16 at 16:45
  • And `max` should be `INT_MIN` actually - for the same reason `min` is `INT_MAX`. – too honest for this site Jan 07 '16 at 16:46
  • @Olaf Added the reference, and modified the INT_MIN thingy. :) – Sourav Ghosh Jan 07 '16 at 16:48
  • Thanks for providing the info. Sorry I was just too lazy to find myself (you forget such references if you are used to avoid such situations intuitively - and use a compiler which warns if you actually did;-). – too honest for this site Jan 07 '16 at 16:48
  • @Olaf It's ok. I understand your point. Cheers. :) – Sourav Ghosh Jan 07 '16 at 16:53
  • Actually Annex J is only informative. According to [this answer](https://stackoverflow.com/a/11965368/1633665) and its comments, things are much messier than that (after all, we're talking about the C standard, it can't be simple) and the main reason why this is UB is that address of `min` and `max` are not taken. – Virgile Jan 07 '16 at 18:23
  • @Virgile: informative only means it bundles information stated already in other sections. Yet these statements are no way optional. Please read its [very first sentence](http://port70.net/~nsz/c/c11/n1570.html#Jp1). – too honest for this site Jan 07 '16 at 22:14
  • @Olaf I'm sorry to play a language lawyer here, but informative annexes are there for information only. This is clearly stated in [ISO/IEC Directives, Part 2](http://isotc.iso.org/livelink/livelink?func=ll&objId=10562502&objAction=download&viewType=1) 6.4.1: "Informative annexes [...] shall not contain requirements, except [...] optional requirements. [...] There is no need to comply with these requirements to claim compliance with the document" – Virgile Jan 08 '16 at 08:03
  • @Virgile: Did you even read the linked first sentence of that annex? Also see its sections. For example the one about _implementation defined behaviour_ clearly states "A conforming implementation is required to document its choice of behavior ...". That is not not optional. As I clearly wrote before and linked paragraph states, too, all subjects listed in this annex are already given by other parts of the document. Feel free to verify this. This clearly is the reason why this is called "informative": it is simply redundant and just a courtesy by the writers. – too honest for this site Jan 08 '16 at 08:27
  • @Olaf I probably should have been more clear. I of course agree that most of the annex can be found in the main body (3.4.1 and 4§8 for your example), but my point is that it is **not** redundant (or to be fair slightly imprecise) when it says that any reading of an indeterminate value results in undefined behavior. Unless I have overlooked something (and in any case, nothing of the sort is stated in any of the sections 6.2.4, 6.7.9 or 6.8 mentioned by the item), the main body of the standard says so only when the variable could have been declared with `register` storage class (6.3.2.1). – Virgile Jan 08 '16 at 16:34
  • @Virgile: It might not have been stated explicitly, but can likely be deduced from other requirements (that's why I asked for a reference, although I was sure Sourav is correct) - this is another reason for annex J. Finally: local definitions commonly override global ones, I'm very confident the linked paragraph is authoritative - whatever other documents might state. So I actually don't care if it just states (or concentrates) redundant information; it is mandatory like the rest. That is commonly accepted interpreation. – too honest for this site Jan 08 '16 at 16:39
0
if(marks[i]>max){
    max = marks[i];
}
else  if(marks[i]<min){
    min = marks[i];
}

min and max are not initialized here. Make sure to set your compiler warnings at the highest level, so you get a warning message when you forget to initialize variables.

for(i;i<=sizeof(marks);i ++){

This doesn't make sense. Replace sizeof(marks) with the number of times you want to loop, and use < instead of <=.

For example:

const int num_marks = 20; // or use #define
int marks[num_marks];
for(i = 0; i < num_marks; i++) {}
Danny_ds
  • 11,201
  • 1
  • 24
  • 46