为所有

时间:2015-05-12 16:30:58

标签: c arrays struct

我需要使用零

来全部化我的struct数组

我的结构:

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

typedef Student* CLASS;

我有这段代码:

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

不应该没有calloc初始化cls中的所有内容为零?如果我打印cls或cls [0]我得到垃圾值;

1 个答案:

答案 0 :(得分:1)

由于讨论了如何发生这种情况,以下是对原始帖子中代码的解释。

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));
}

现在我们有一个6800字节的数组,用零填充。

让我们来看看printf("%s")个参数的所有选项。

“%s”需要一个指向以null结尾的字符串的char *指针。由于printf是一个变量参数函数,它不知道参数的真实类型, 它只会假设它们。

请注意,某些编译器可以检查arg类型,但这不是语言的一部分。

printf("%s", cls);

这里,cls指向6800个零字节数组的开头。 ((char*)cls)[0] == '\0',因此它会立即终止,并且不会打印任何内容。

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

由于(char*)(cls[0])是空指针,因此将使用空指针解除引用而崩溃。该程序将崩溃,但不会打印出垃圾。

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

这实际上相当于第一次打印,只是转换为其他类型。但是因为printf从格式字符串中推断出类型信息,而不是参数,所以它的行为相同。

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

这通常是一个坏主意,但它仍然没有打印。那是因为指针指向零初始化数组中的某个位置,这意味着当取消引用时,你仍然会先命中零。

打印垃圾的唯一方法是:

printf("%s", &cls);

这里我们传递一个指向cls的指针,并说它是一个指向char数组的指针。假设calloc返回0xdeadbeef,当解除引用双指针时,我们将地址视为一个字符串,因此printf将打印出0xef, 0xbe, 0xad, 0xde的ASCII值及其后的任何内容,直到它击中0x00或移动了一个不属于该进程的地址并导致访问冲突。第一种情况更有可能。

编辑:显然,另一个答案和讨论的主题已被删除。我将这里留给未来的访客。