我有一个非常普遍的问题,当我尝试将字符数组写入文件时,我将代码编写为
fwrite(array[10],1,10,file_ptr)
编译器发出警告argument 1 makes from integer to pointer without a cast.
然后我将这一行修改为
fwrite(&array[10],1,10,file_ptr)
并且警告现在不再出现。
问题:编译器如何区分地址和值?如果 at 的值array[10]
类似于正确的地址怎么办?
我有一个非常普遍的问题,当我尝试将字符数组写入文件时,我将代码编写为
fwrite(array[10],1,10,file_ptr)
编译器发出警告argument 1 makes from integer to pointer without a cast.
然后我将这一行修改为
fwrite(&array[10],1,10,file_ptr)
并且警告现在不再出现。
问题:编译器如何区分地址和值?如果 at 的值array[10]
类似于正确的地址怎么办?
如果你有一个十个字符的数组,即
char array[10];
然后做array[10]
访问该数组的第十一个元素。
只需传递数组变量,它就像一个指针:
fwrite(array, 1, 10, file);
C 是一种静态类型语言。每当你写
char array[100];
你告诉 C 编译器这array
是一个 100 个字符的数组。然后,它知道那array[10]
是一个字符,那&array[10]
是一个指向字符 (a char *
) 的指针。
fwrite
但是,它被定义为将 aconst void *
作为其第一个参数,即一个无类型指针。如果你传递了一些不是指针的东西,编译器就会知道这一点并会抱怨。
您的 C 编译器不会尝试根据某事物的值“猜测”某事物的类型。
的签名fwrite()
是:fwrite(const void *ptr, size_t size, size_t count, FILE *fptr)
。
fwrite()
期待一个地址(或一个保存地址的指针变量,也就是指针)而不是一个字符,但是,
a[10]
是一个字符,而不是一个指针。这是警告的原因!
&a[10]
是一个地址,有效地适合作为 的第一个参数fwrite()
。因此不会引发任何警告!
它如何保存信息是在它的词法分析器+解析器组合和语义分析器中的一个名为“符号表”的表中。
-- 修改问题后 --
fwrite(&array[10],1,10,file_ptr)
<- argument-1 被解释为从第 11 个位置开始的字符串array
似乎您的印象是array[10]
指定整个数组 - 它没有。它指定 的第十一个元素array
,该元素不存在(假设您将其声明为some_type array[10]
)。
既然你说你想写整个数组,你需要传递 fwrite() 的第一个元素的地址array
,这恰好是array
(或&array[0]
),因为在 C 中,当在表达式中使用时数组的名称,是其第一个元素的地址(sizeof
运算符除外)。
编译器具有有关数组类型和元素类型的完整信息,因此它可以检测您何时int
在需要指针的地方编写类型表达式。
有一种方法可以 fwrite() 一个完整的数组,与大小和元素类型无关,只需使用数组标识符:
fwrite (array, sizeof *array, sizeof array/sizeof *array, file);
其中sizeof *array
计算元素大小并sizeof array/sizeof *array
计算数组中元素的数量。请注意,这仅适用于数组,不适用于指针。同样可以实现
fwrite (array, sizeof array, 1, file);
或者
fwrite (array, 1, sizeof array, file);
这主要是您喜欢的风格问题;它们都是等效的,并且将以相同的速度执行。
如果 array[10] 的值类似于正确的地址怎么办?
那么您的数组类型将是int (*)[n]
,而不是int [n]
。这就是我们有类型系统的原因。