我需要使用零
来全部化我的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]我得到垃圾值;
答案 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
或移动了一个不属于该进程的地址并导致访问冲突。第一种情况更有可能。
编辑:显然,另一个答案和讨论的主题已被删除。我将这里留给未来的访客。