重新学习 c 语言(3)- c语言特性(三)函数和程序结构

(三)函数和程序结构

1.函数

函数调用非常依赖编译实现,函数的参数和返回值一般存放在线程堆栈中.

对于c语言,函数都是外部的!(函数中不能包含函数)

重要的一条,函数的参数传递统一为值传递

这一点很重要!

一般来说,在调用一个函数时,参数是放在栈里的(有时候编译器会把参数放到寄存器中,不影响我们讨论),值传递的意思是,编译器会将传递给函数的参数(我这里不打算引入形参和实参的概念,其实或许无助于理解)的值赋值到栈中,这样的处理会使编译简单,也使程序员容易理解.

int AddTen(int aNum)
{
  return aNum + 10;
}
int a =100;
int main()
{
  int b =AddTen(a);
 return 0;
}

调用函数AddTen 时 变量a的值 100 被赋值到栈中,也就是在函数AddTen中 aNum是一个局部变量,值是100.

传值的缺点是明显的,如果参数尺寸很大,则复制会影响性能,而且大多数复制是没有必要的!

另外,如果一个函数有多个返回值怎么办?

有经验的C程序员在传递尺寸大的参数或者需要多个返回值时,会采用传递指针的方法:

比如上面定义的struct String

int getStringLen(struct String *str);

需要注意的一个问题是数组,在c语言中,数组名其实就是数组第一个元素的地址!

数组名作为参数传递,在函数的局部变量中引用的是一个地址,其实该局部变量就是一个指针.

比如 int a[]={1,2,3,4,5};

对a的引用其实是相当于&a[0];仅仅如此而已;

比如函数

int sum(int a[],int aLen)
{
  int result = 0;
  for (int i=0 ;i

调用是这样的 int total = sum(a,5);

对于一个数组,知道其元素类型(int),第一个元素地址&a[0],还有数组长度(5),就能完全操作一个数组了,结合前面讨论的指针的运算特性,就可以用指针方便的操作数组了.

2 程序结构

先简单的说说程序的控制流,

一个程序的运行只有三种控制流:

  • 顺序

  • 选择

  • 循环

其实,只要有if 和goto (汇编里的jmp),就可以实现上面的三种程序控制流.
C语言里表示选择的除了if else 语句 还有 switch case 语句
循环也只有 while for 和 do while 三种语句.(break 和 continue 只是限制性的goto)
因为简单所以K&R中也只是讲了10页的内容

由于c语言是严格的将声明和定义分开的,甚至使用.h来表示声明(不是绝对的),.c文件表示定义.但这样做的优点是明显的.尤其是对于编译器来说.Pascal程序虽然没有明显的区分.h和.c两个文件中,但也通过一个文件中interface和implementation关键字来区分.

一个c程序,就是若干.h的头文件(声明文件)和若干个.c的文件(定义文件)里包含若干个函数和外部变量.就是这样简单.
下一篇:重新学习 c 语言(4)- 库和宿主实现(一)概论
前一篇:重新学习 c 语言(3)- c语言特性(二)数据对象

你可能感兴趣的:(重新学习 c 语言(3)- c语言特性(三)函数和程序结构)