1

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;

7
  • calloc does fill the memory with zeroes. How are you printing it exactly? Commented May 12, 2015 at 16:34
  • 1
    Show how you are printing the pointer cls? Commented May 12, 2015 at 16:35
  • After you both making reference to how i was printing it, i found out that the problem was that! Thank you very much. @mtijanic , could you answer that so i can mark as the right answer? Commented May 12, 2015 at 16:40
  • in C, the returned value from calloc(), and family of functions, should not be cast. Commented May 12, 2015 at 16:46
  • @user3629249, if i don't cast, will the value returned from calloc be a pointer for a Student struct type, to the memory allocated? Commented May 12, 2015 at 16:56

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.