当我从函数内部调用memset时,我试图弄清楚为什么memset不起作用。 当然,我可以使用for循环来重置所有值,但是我在这里学习的是,这件事使我没有任何解释。
/* First source code */
#include <stdio.h>
#include <string.h>
int main(void) {
int i, j, num;
printf("Digit a number :");
scanf("%d", &num);
int magic[num][num];
printf("First\n");
for(i = 0; i < num; ++i) {
for(j = 0; j < num; ++j) {
printf("%4d", magic[i][j]);
}
printf("\n\n");
}
memset(magic, 0, sizeof(magic));
printf("Before\n");
for(i = 0; i < num; ++i) {
for(j = 0; j < num; ++j) {
printf("%4d", magic[i][j]);
}
printf("\n\n");
}
return 0;
}
/* Second source code */
#include <stdio.h>
#include <string.h>
void create_magic_square(int n, int magic_square[][n]);
void print_magic_square(int n, int magic_square[][n]);
int main(void) {
int num;
printf("Digit a number :");
scanf("%d", &num);
int magic[num][num];
create_magic_square(num, magic);
return 0;
}
void create_magic_square(int n, int magic_square[][n]) {
int i, j;
printf("First\n");
for(i = 0; i < n; ++i) {
for(j = 0; j < n; ++j) {
printf("%4d", magic_square[i][j]);
}
printf("\n\n");
}
//memset(magic_square, 0, n * sizeof(magic_square[0]));
memset(magic_square, 0, sizeof(magic_square));
printf("Before\n");
for(i = 0; i < n; ++i) {
for(j = 0; j < n; ++j) {
printf("%4d", magic_square[i][j]);
}
printf("\n\n");
}
}
在第二个代码(带有函数)中,我应该把这一行: memset(magic_square,0,n * sizeof(magic_square [0])); 用于清除二维数组,同时具有: memset(magic_square,0,sizeof(magic_square)); 不起作用。为什么会这样?
答案 0 :(得分:5)
当您将数组传递给C语言中的函数时,即使您在函数原型中指定了数组类型,它们也会衰减为指向数组中第一个元素的指针, (a)。因此,sizeof
将为您提供指针的大小,而不是数组的大小。
常见的做法是将数组大小与数组一起传递(可能是size_t
),并使用 that 编织魔术,例如:
int zeroArray(void *address, size_t sz) { // void* makes it clear
memset(address, 0, sz); // but int thing[][] would be same.
}
:
int xyzzy[42][7];
zeroArray(xyzzy, sizeof(xyzzy));
但是,您已经已经向当前函数传递了足够的信息来执行此操作,特别是n
。您应该能够使用它来为sizeof
运算符形成一个类型(可以使用变量或一个类型),它将满足您的需要:
memset(magic_square, 0, sizeof(int[n][n]));
(a)在C11
部分下的最新标准6.3.2.1 Lvalues, arrays, and function designators /3
中涵盖:
除非它是
sizeof
运算符,_Alignof
运算符或一元&
运算符的操作数,或者是用于初始化数组的字符串文字,将类型为“数组类型”的表达式转换为类型为“指针类型”的表达式,该表达式指向数组对象的初始元素,而不是左值。
尽管您使用了c99
标签,但我还是引用了该标准的 latest 迭代,唯一的区别是C99标准没有提及Alignof
,因为它不存在在那个迭代中。除此之外,报价是相同的。
这可以追溯到,甚至可以追溯到K&R第一版5.3 Pointers and arrays
:
实际上,编译器将对数组的引用转换为指向数组开头的指针。