skills
skills

Reputation: 327

Initialize struct array with zero value for all

I need to inizialize my array of struct with all at zero

my struct:

typedef struct stud
{
    char nome[60];
    int num;
    int nota;
} Student;

typedef Student* CLASS;

I have this code:

int main(){
    CLASS cls;
    cls = (CLASS) calloc(100,sizeof(Student));
    if (cls==NULL) printf("Error allocating memory");
}

Shouldn't calloc initialize all content from cls at zero? If i print cls or cls[0] i get garbage values;

Upvotes: 1

Views: 428

Answers (1)

mtijanic
mtijanic

Reputation: 2902

Since there was a discussion on how this could have happened, here is an explanation of the code in the original post.

typedef struct stud
{
    char nome[60];
    int num;
    int nota;
} Student;
// This structure is most likely 68 bytes in size:
// sizeof(Student) == 68
// offsetof(Student, nome) == 0
// offsetof(Student, num) == 60
// offsetof(Student, nota) == 64

int main(){
    // Allocate an array of 100 Students, for a total of 6800 bytes.
    // Note that calloc fills the memory with zeroes.    
    Student *cls = calloc(100, sizeof(Student));
}

Right now we have an array of 6800 bytes filled with zeroes.

Let's go through all the options of printf("%s") arguments.

"%s" expects a char* pointer to a null-terminated string. Since printf is a variable arguments function, it doesn't know the true type of the argument, it will just assume them.

Note that some compilers can check the arg types, but that isn't part of the language.

printf("%s", cls);

Here, cls points to the start of an array of 6800 zero-bytes. ((char*)cls)[0] == '\0', so it terminates immediately, and nothing is printed.

printf("%s", cls[0]);

Since (char*)(cls[0]) is a null pointer, this will crash with a null pointer dereference. The program will crash, but no garbage would be printed out.

printf("%s", cls[0]->nome);

This is actually equivalent to the first print, just cast to a different type. But since printf infers type info from the format string, not the arguments, it acts the same.

printf("%s", &cls[5]->num);

This would generally be a bad idea, but it still would print nothing. That is because the pointer points to somewhere in the zero-initialized array, meaning that when dereferenced, you'd still hit a zero first.

The only way to print out garbage is with:

printf("%s", &cls);

Here we pass a pointer to cls, and say it's a pointer to a char array. Assuming calloc returned 0xdeadbeef, when dereferencing the double pointer, we'd be treating the address as a string, so printf would print out the ASCII values of 0xef, 0xbe, 0xad, 0xde and whatever comes after it, until it either hit a 0x00 or moved hit an address not belonging to the process and caused an access violation. The first scenario is much more likely.


EDIT: Apparently the other answer and the thread with the discussion was deleted. I'll leave this here for future visitors.

Upvotes: 1

Related Questions