地址、函数声明与定义

2018年11月5日的实验课上出现一些问题:

1. A与&A

若有数组int A[]={0,1,2};

1
2
printf("%p\n",A)
printf("%p\n",&A)

输出的结果是一致的,两者指向的同一块地址,不同的是A代表的是数组首元素的地址,&A代表的整个数组的地址。
所以当

1
2
printf("%p\n",A+1)
printf("%p\n",&A+1)

A+1增加的一个元素的内存大小(增加4);
&A+1增加的是整个数组的内存大小(增加12)

2. 函数的参数是数组,取地址

如果主函数中调用了f(A); f的定义如下

1
2
3
4
5
6
7
int f(int x[]) {

printf("%p\n",&x);
printf("%p\n",x);
return 0;

}

此时输出的并不同,后者x输出的是A的首元素地址,前者输出的x的地址(指针变量的地址)

3. 声明和定义的位置

助教课程中有同学程序出错,最后对错误的原因探索了一下。
一般说来,子函数的声明和定义,参数个数要一致,但是奇怪的是发现参数不一致有些情况下居然编译是正常的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
void g() {
printf("JY");
}

void main() {
int a=3,b=4,c=5;
int A[5]={0,1,2,3,4};
printf("%p\n",&A);
void f();
f();
}

void f(int x) {
printf("%p\n",x);
g();
}

首先,c语言不支持重载。
在函数调用和定义参数不匹配时——

有声明(且声明和调用的参数上一致,否则编译先出错),编译出错

  • 定义在main之前,编译出错。编译器先有了定义,读到调用的地方,会做参数个数类型检查(虽然并不完善),与先前定义的不一致,所以给出编译出错。
  • 定义在main之后,编译出错。奇怪的是定义函数f时的参数若写成int x[],没有出错。应该是传递了什么地址直接给指针变量x了吧?待考察。

没有声明,编译大多数出错

  • 定义在main之前,编译出错,同上解释;
  • 定义在main之后,都是编译出错解释同上,但是除非:如果定义f的返回值是int(因为c语言默认函数的返回值都是int,对于main中的f();默认其是int,只有定义f的返回值也是int才相符)编译只是警告。因为在编译期间,没有声明,编译器不知道函数原型是什么,更别提什么检查。
    那链接期检查吗,编译通过说明没有重载,链接期间以函数名作为符号的识别依据,发现函数名一致就通过链接阶段了。

综上所述,书写函数,把声明在开头写好(比如写进头文件),好好比对参数类型和个数。