注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。
测试环境:Ubuntu 10.10
GCC版本:4.4.5
一、C语言中的函数
1) 函数的由来
二、函数的意义
1) 模块化程序设计
2) C语言中的模块化
三、面向过程的程序设计
1) 面向过程是一种以过程(解决问题的过程)为中心的编程思想
2) 首先将复杂的问题分解为一个个容易解决的问题
3) 分解过后的问题可以按照步骤一步步完成
4) 函数是面向过程在C语言中的体现
5) 解决问题的每个步骤可以用函数来实现
四、声明和定义
1) 声明的意义在于告诉编译器程序单元的存在
程序单元:是指在程序中执行某一特定任务的具有一定独立性的代码模块
2) 定义则明确指示程序单元的意义
3) C语言中通过extern进行程序单元的声明
4) 一些程序单元在声明时可以省略extern
严格意义上的声明和定义并不相同!
实例分析
声明和定义不同
global.c
#include
int g_var = 10;
struct Test
{
int x;
int y;
};
void f(int i, int j)
{
printf("i + j = %d\n", i + j);
}
int g(int x)
{
return (int)(2 * x + g_var);
}
43-1.c
#include
#include
extern int g_var; //声明g_var,g_var的内存分配在别的空间
extern struct Test; //声明结构体,这里的extern可以省略
int main()
{
extern void f(int i, int j); //声明函数,告诉编译器不要报错
extern int g(int x); //声明函数
struct Test* p = NULL; // (struct Test*)malloc(sizeof(struct Test));
printf("p = %p\n", p);
//g_var = 10;
printf("g_var = %d\n", g_var);
f(1, 2);
printf("g(3) = %d\n", g(3));
free(p);
return 0;
}
操作:
1) gcc 43-1.c global.c -o 43-1.out编译有警告:
43-1.c:6:15: warning: useless storage class specifier in empty declaration [enabled by default]
extern struct Test;
^
警告:在空的类型申明中,说明符没有意义
打印结果:
p = (nil)
g_var = 10
i + j = 3
g(3) = 16
2) 修改代码:
#include
#include
extern int g_var; //声明g_var,g_var的内存分配在别的空间
extern struct Test; //声明结构体,这里的extern可以省略
int main()
{
extern void f(int i, int j); //声明函数,告诉编译器不要报错
extern int g(int x); //声明函数
struct Test* p = (struct Test*)malloc(sizeof(struct Test));
printf("p = %p\n", p);
//g_var = 10;
printf("g_var = %d\n", g_var);
f(1, 2);
printf("g(3) = %d\n", g(3));
free(p);
return 0;
}
gcc 43-1.c global.c -o 43-1.out编译错误:
43-1.c:6:15: warning: useless storage class specifier in empty declaration [enabled by default]
extern struct Test;
^
43-1.c: In function ‘main’:
43-1.c:13:47: error: invalid application of ‘sizeof’ to incomplete type ‘struct Test’
struct Test* p = (struct Test*)malloc(sizeof(struct Test));
^
错误:非法应用sizeof在不完全类型'struct Test'
分析:
struct Test只是被声明,虽然在其它地方被定义,但是编译时有先后顺序(定义struct Test的文件被先编译后,才能在申明的struct Test的地方被使用),我们不能依赖于编译文件的顺序设计代码。
3) 修改g_var类型为float类型,代码如下:
global.c
#include
float g_var = 10; //内存中以浮点数格式存储数据
struct Test
{
int x;
int y;
};
void f(int i, int j)
{
printf("i + j = %d\n", i + j);
}
int g(int x)
{
return (int)(2 * x + g_var);
}
43-1.c
#include
#include
extern int g_var; //声明g_var为int类型,以定义时不符
extern struct Test; //声明结构体,这里的extern可以省略
int main()
{
extern void f(int i, int j); //声明函数,告诉编译器不要报错
extern int g(int x); //声明函数
struct Test* p = NULL;
printf("p = %p\n", p);
//g_var = 10;
printf("g_var = %d\n", g_var);
f(1, 2);
printf("g(3) = %d\n", g(3));
free(p);
return 0;
}
gcc 43-1.c global.c -o 43-1.out编译有警告:
43-1.c:6:15: warning: useless storage class specifier in empty declaration [enabled by default]
extern struct Test;
^
运行结果:
p = (nil)
g_var = 1092616192
i + j = 3
g(3) = 16
分析:
定义时g_var为float类型,但是打印时按照整型解释g_var,因此会产生这么大的数据。
注:
1. C语言中的声明不分配内存,仅仅是告诉编译器这里有这个东西;定义才分配内存。
小结:
1) 函数是面向过程思想在C语言中的体现
2) 面向过程是由上至下分解问题的设计方法
3) 程序中的定义和声明完全不同
4) C语言中通过extern对程序单元进行声明