第三章, C语言的函数
1.
可以这样说, C程序都是由函数构成的. 从程序的入口到调用某一代码块, 都是由函数构成的.
C程序不像PHP那样直接写到PHP文件就可以运行的, C程序要有一个程序的入口, 叫main函数, 一切都从main函数开始,也从main函数结束.
C语言的函数跟PHP的相似, 不过也有不同, 下面是C语言的函数定义方式:
返回值类型 函数名(参数1, 参数2…) {
}
例如:
int main(int argc, char **argv) {
}
例子的int就是返回值类型, main就是函数名, argc是参数1, argv是参数2, printf是代码段, return 0就是返回0.值得注意的是, 参数也必须指定类型, 如参数1是int类型, 参数2是char**类型的.
2.
C语言跟PHP一样也有全局变量和局部变量, 不过使用就大有不同了. 在C语言里要定义一个全局变量, 只需要在函数体外面定义就可以了, 例如:
#include <stdio.h>
int ivar = 5;
void print_ivar() {
}
int main(int argc, char **argv) {
}
输出结果:
上面的程序中, 我们定义了一个全局的变量ivar, 然后所有的函数都可以使用这个全局的变量, 如上面代码的print_ivar()函数就打印了ivar和main函数把ivar的值设为了10.
从程序中看出, C语言在函数中使用全局变量不用像PHP那样使用关键字global来声明这个变量是全局的, 在C语言中函数可以直接使用全局变量.
那么我们应该怎么定义一个局部变量呢? 其实也和简单, 只有在函数体里面直接定义一个变量, 这个变量就是局部变量了. 例如:
#include <stdio.h>
void print_ivar() {
}
int main(int argc, char **argv) {
}
在print_ivar()函数中, 我们定义了一个int的局部变量ivar, 并赋值为10.
如果我们在其他函数改变这个变量的值会怎么样呢? 如下:
#include <stdio.h>
void print_ivar() {
}
int main(int argc, char **argv) {
}
编译的结果:
可以看出, 其他函数不能改变一个不属于自己的局部变量, 如果这样做, 编译器会编译不通过.
现在有个问题, 就是如果我们定义了一个全局变量ivar, 然后我们也在函数里面定义了一个局部变量ivar, 那会怎样呢?如果这种情况的话, 在函数体里面这样使用ivar的局部变量, 而不能使用ivar的全局变量, 如下:
#include <stdio.h>
int ivar = 10;
void print_ivar() {
}
int main(int argc, char **argv) {
}
在上面的程序中, 我们定义了一个全局的变量ivar赋值为10, 然后在print_ivar()函数中也定义了一个局部变量ivar赋值为5. 在main函数中, 我们首先打印了全局变量ivar的值, 然后调用了print_ivar()函数, 最后再一次打印全局变量ivar的值. 运行结果如下:
从运行结果可以看出, 改变print_ivar()函数局部变量ivar的值并不影响全局变量ivar的值.
3.
什么是头文件? 要了解头文件, 首先要知道怎样把多个C文件编译成一个程序.
例如我们在一个C文件print_ivar.c中定义了一个函数print_ivar(), 然后在main.c文件中调用print_ivar()这个函数应该怎么办呢?
print_ivar.c
#include <stdio.h>
void print_ivar() {
}
main.c
#include <stdio.h>
int main(int argc, char **argv) {
}
然后我们编译main.c, 会发现编译不通过, 错误信息如下:
就是说找不到print_ivar()这个函数, 所以可以看出, print_ivar.c的文件并没有包含进来, 所以我们要把他包含进来, 怎么包含? 跟PHP差不多, 使用#include宏, 如下:
#include <stdio.h>
#include "print_ivar.c"
int main() {
}
在上面我们使用#include "print_ivar.c"这个语句来把print_ivar.c包含进来了. 嗯, 这次就可以编译通过, 并且成功调用了print_ivar()函数了.
如果在PHP里, 这样来包含文件是比较常见的, 但是在C语言里面这样做就不太好了, 为什么这样说? 因为如果你想了解print_ivar()函数是怎么使用的话, 就必须打开print_ivar.c, 然后看看print_ivar()的定义, 才知道怎么调用它.但是如果这个.c的文件非常庞大, 有1万多行, 那看起来就没有那么轻松了, 所以C语言使用头文件来解决这个问题.
头文件一般以.h作为后缀名, 是用来声明函数, 结构体和变量的. 例如:
print_ivar.h
void print_ivar();
然后我们在main.c中包含进来:
#include <stdio.h>
#include "print_ivar.h"
int main() {
}
这次我们使用gcc来编译, 如果想用codeblocks编译的话也可以, 不过要做一些额外的工作.
gcc编译命令是: gcc main.c print_ivar.c print_ivar.h –o main
嗯, 编译通过, 而且正确运行了. 以后你只需要看看print_ivar.h是怎么调用print_ivar()这个函数就可以了, 而不要去看print_ivar.c了, 这样可以免除了很多不必要的麻烦.
4.
和PHP一样, C语言也有静态变量, 而且跟PHP的使用是一样的, 使用static关键字来声明, 如下:
#include <stdio.h>
void print_ivar() {
}
int main() {
}
我们在print_ivar()函数中定义了一个静态变量, 初始化为0, 然后打印ivar变量和把ivar的值加一, 在main函数中调用了三次print_ivar()函数, 输出如下:
可以看出, ivar不段的累加了, 而没有每次都把ivar初始化为0. PHP中的静态变量也是这样, 所以也不用多说了.
5.
PHP的函数也有返回值, 而且都是通过return关键字来返回的, 不过跟PHP不一样的就是, C语言的返回值要跟函数定义时的返回值类型一致, 不然编译器会报错. 如我们定义的函数需要返回一个char*类型的值, 但是你却返回一个int的值,编译器就会报错, 如:
#include <stdio.h>
char *return_str() {
}
int main() {
}
编译器就会报错, 如下:
就是说, 函数返回值类型跟定义的不一致, 而且又没有使用强类型转换. 从提示中可以看出, 使用强类型转换可以通过编译的, 如:
#include <stdio.h>
char *return_str() {
}
int main() {
}
在返回值中, 使用强类型转换(char *)就可以通过编译了.
函数已经讲完了, 下章讲一下宏.