用零值初始化结构数组
Initialize struct array with zero value for all
我需要将我的结构数组初始化为零
我的结构:
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] 我得到垃圾值;
由于讨论了这是如何发生的,这里是对原始代码的解释 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));
}
现在我们有一个用零填充的 6800 字节的数组。
让我们看一下 printf("%s")
个参数的所有选项。
"%s" 需要一个指向空终止字符串的 char* 指针。由于 printf 是可变参数函数,它不知道参数的真实类型,
它只会假定它们。
请注意,某些编译器可以检查 arg 类型,但这不是语言的一部分。
printf("%s", cls);
这里,cls 指向 6800 个零字节数组的开始。 ((char*)cls)[0] == '[=17=]'
,所以它立即终止,没有打印任何内容。
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 值以及它后面的任何内容,直到它命中a 0x00
或 moved 命中不属于该进程的地址并导致访问冲突。第一种情况更有可能。
编辑:显然其他答案和讨论主题已被删除。我会把它留在这里供以后的访客使用。
我需要将我的结构数组初始化为零
我的结构:
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] 我得到垃圾值;
由于讨论了这是如何发生的,这里是对原始代码的解释 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));
}
现在我们有一个用零填充的 6800 字节的数组。
让我们看一下 printf("%s")
个参数的所有选项。
"%s" 需要一个指向空终止字符串的 char* 指针。由于 printf 是可变参数函数,它不知道参数的真实类型, 它只会假定它们。
请注意,某些编译器可以检查 arg 类型,但这不是语言的一部分。
printf("%s", cls);
这里,cls 指向 6800 个零字节数组的开始。 ((char*)cls)[0] == '[=17=]'
,所以它立即终止,没有打印任何内容。
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 值以及它后面的任何内容,直到它命中a 0x00
或 moved 命中不属于该进程的地址并导致访问冲突。第一种情况更有可能。
编辑:显然其他答案和讨论主题已被删除。我会把它留在这里供以后的访客使用。