2013-02-26 226 views
2

我有一个非常普遍的问题,当我试图写一个字符数组到一个文件中,我写的代码C编译器警告

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

你能告诉我们'array'的声明吗? – Jens 2013-02-26 09:07:03

回答

1

C是静态类型语言。当你写

char array[100]; 

你说的是C编译器是array是100个字符数组。然后,它知道array[10]是一个字符,而&array[10]是一个指向字符的指针(一个char *)。

fwrite虽然被定义为将const void *作为其第一个参数,即无类型指针。如果你通过它不是一个指针,编译器知道这一点,并会抱怨。

您的C编译器不会尝试“猜测”某种东西的类型是基于它的值。

4

如果有十个字符的阵列,即

char array[10]; 

然后做array[10]访问该阵列的第十一元件。

简单地传递数组变量,它可以作为一个指针:

fwrite(array, 1, 10, file); 
+0

+1,因为您指出了错误,但“作为指针工作”更像是“衰减成指针”。 – 2013-02-26 08:20:29

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) < - 参数-1被解释为从11位置开始的字符串中array

+3

地址不一定是4个字节宽,它与问题无关。而且你也不需要提及词法分析器和解析器。 – 2013-02-26 08:34:11

+0

@AlexeyFrunze我之所以提到这一切是因为'编译器如何区分地址和值?如果数组[10]的值与正确的地址相似,该怎么办? – 2013-02-26 08:37:10

+0

编译器跟踪变量类型,这足以让人知道。 – 2013-02-26 08:39:58

1

看来你的印象是array[10]指定下整个数组 - 它不。它指定array的第11个元素,它不存在(假设您声明为some_type array[10])。因为在C中,名称是一个数组,因此您需要将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); 

它基本上是你喜欢的风格问题来实现;它们都是等效的,并且将以相同的速度执行。

0

如果数组[10]的值类似于正确的地址会怎么样?

那么你的数组类型本来int (*)[n],而不是int [n]。这就是为什么我们有一个类型系统。