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