1.如果你有一些声明需要用于几个不同的源文件,这个技巧也是一个方便的方法---你在一个单独的文件中编写这些声明,然后用#include指令把这个文件包含到需要使用这些声明的源文件中,这样你就只需要这些声明的一份拷贝,用不着再许多不同的地方进行复制,避免了在维护这些代码时出现错误的可能性。
2.#include 、宏定义之类的都属于预处理指令(preprocessor directives),是由预处理器解释的,预处理器读入源代码,根据预处理指令进行修改,然后把修改过的源代码交给编译器。
3.宏定义一般都是大些,用于提醒它们并非普通的变量。
4.函数声明被称为函数原型(function prototype),他们告诉编译器这些以后将在元文件中定义的函数的特征。这样,当这些函数被调用时,编译器就能对它们进行准确性检查,每个原型以一个类型名开头,表示返回值的类型。跟在返回类型后面的是函数的名字,再后面是函数期望接受的参数。函数原型中参数的名字并非必须,我们一般给出参数的名的目的是提示它们的作用。
5.void rearrange(cahr * output,char const *input,int n_columns,int const columns[])
上面函数中接受4各参数,其中第一个和第二个都是指针(pointer).指针指定一个存储于计算机内存中的值的地址。第二个和第四个参数被声明为const,这表示函数将不会修改函数调用者所传递的这两个参数。
6.函数原型如果没有参数,()中最好写个void.
7.在C语言中,数组参数是以引用(reference)形式进行传递的,也就是地址调用,而标量和常量则是按值(value)传递的。在函数中对传入的标量参数的任何修改都会在函数结束时丢失,函数调用结束时,对传入的标量参数在函数体中的修改丢失恢复到调用之前。因此,被调用函数无法修改调用函数以传值形式传递给它的参数。然而,当被调用函数修改数组参数的其中一个元素时,调用函数所传递的数组就会被实际的修改。
int test(int input,int test[ ]);
//不管传进来的一维数组里面存多少个数据,形参都不管,只写明数组存放的数据类型(在这里是int)即可
int test(int input,int test[ ])
//不管传进来的一维数组里面存多少个数据,形参都不管,只写明数组存放的数据类型(在这里是int)即可
{
//数组的名字退化为第一个元素的地址,此时test是test数组的首地址,取*意思是首地址中存放的数据
//所以下一句中的x=1
int x = *test;//此时test的值是0x0012f2f0
test++;
int y = *test;
//经过上一步test的值是0x0012f2f4 (因为int在当前机器中是占4个字节,所以指针+1,地址移动4个字节0x0012f2f0+4)
input +=10;//此时i变为110
int iNum = sizeof(int); //int类型数据在当前机器占用字节数量
test++;
test[0]=100;
//经过上一步指针移动此时test值是0x0012f2f4+4=0x0012f2f8
return input;
}
void main(void) // 良好的代码风格
{
int i = 100;
int t[5] = {1,2,3};//假设数组t的首地址是0x0012f2f0
int re = test(i,t);//将数组名传进去即可,即传递进去的是t的首地址0x0012f2f0
//函数调用结束,由于i是值传递,此时i的值恢复为100
//函数调用结束,由于数组t是引用传递,将地址传递进来,修改了地址内存放的数据,故函数调用结束,传递进来的地址没变,但地址里面存放的数据变了,此时t[0]=100 但t的值即数据t的首地址没变,依然是0x0012f2f0
}
其实传数组的引用也还是传递的数组的地址的值,依然是值传递,传进去的是数组的地址值,函数调用结束该地址值不变,但是数组里面存放的数据可以变。