技术笔试面试

《帮你度过C语言新手阶段》系列之二

真正深入学习C语言已经3年有余了。不过还是有很多知识点没有记下来,在此总结一下,也帮助C语言新手度过新手难关。

如果你已经认真阅读过谭浩强C,那么复习如下知识大约需要1个小时,而且保证包括大部分易错知识点:)

本篇是《帮你度过C语言新手阶段》系列的第二篇。

第二十关:

定义函数时,有传统方式和现代方式。

现代方式:

int max(int x,int y){

}

传统方式:

int max(x,y)

int x;

int y;

{

}

第二十一关:

函数的定义和声明不是一回事。

定义是对函数功能的确立,包括指定函数名、函数值类型、形参以及其类型、函数体等,它是一个完整的、独立的函数单位。

声明的作用是把函数的名字、函数的类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。

在函数的声明中完全可以不写形参名,而只写形参的类型。如:float add(float,float);

旧版本的C语言中,函数声明可以只声明函数名和函数返回类型,如int add();

如果在函数调用之前,没有对函数做声明,则编译系统会把第一次遇到的该函数形式作为函数的声明,并将函数返回类型默认为int。所以如下的程序,虽然没有事先声明max函数,但仍可以侥幸通过:

int main()

{

int c=max(2,5);

}

max(int x,int y)

{

int z;

z=x>y?x:y;

return z;

}

可见,没有定义函数类型(即函数返回类型)的函数,都会默认为int型。

上述程序能侥幸通过的原因是return z中的z是int型。如果z是其他任何类型,程序都会报错,即使是相兼容的short、long、char或unsigned int都不行!

第二十二关:

形参数组可以不指定大小,且在形参中int a[]和int a[131212]和int *a是等价的!

形参多维数组的话,只能省略第一维的数组,其他维必须按照正确的值来填写。

第二十三关:

用户存储空间包括:

(1)程序区

(2)静态存储区

(3)动态存储区

全局变量全部放在静态存储区。

动态存储区存放以下数据:

1 函数形参

2 自动变量,即未使用static声明的局部变量

3 函数调用的现场保存和返回地址

在C语言中,每个变量有两个属性:

1 数据类型

2 数据存储类型

第二十四关:

函数中的局部变量,如果不专门声明为static存储类型,则默认都为auto存储类别,都会被分配到动态存储区。auto是一个默认关键字。即int a;等价于auto int a;

静态存储类别的变量,被分配在静态存储区,在程序整个运行期间都不释放。静态局部变量在编译时赋初值,且只赋初值一次,如果用户不指定,则为0。(auto类型变量的话,如果用户不指定初值,则初值是一个不确定的值)

第二十五关:

为了提高效率,C语言允许将局部变量放在CPU中的寄存器里,这种变量叫做“寄存器变量”,如register int a;

只有局部自动变量和形参变量可以作为寄存器变量。

局部静态变量不能作为寄存器变量。

第二十六关:

extern用于声明外部变量,如extern char a,b;

注意,除非引用的外部变量是int型,否则必须写上数据类型,而且和外部变量的数据类型必须完全一致。

第二十七关:

使用#define定义的宏,可以用#undef来取消。

如#define G 9.8,可以用如下命令取消:

#undef G

C程序中,用双引号括起来的部分,不会被宏所代替。

定义计算圆面积的宏,应该注意要加上括号,即:

#define PI 3.14

#define S(r) PI*(r)*(r)

宏名是无类型的,而且它的参数也是没有类型的。

宏替换不占运行时间,只占编译时间。

第二十八关:

头文件,使用.h后缀只是为了表明文件性质。所以,即使没有.h也是没问题的。

头文件里应该可以函数原型、宏定义、结构体类型定义以及全局变量定义。

第二十九关:

&和*的优先级相同,且结合性是自右至左。(单目运算符的结合性是右结合)

*pointer++,由于++和*为同一优先级,而结合性又是自右至左,所以相当与*(pointer++)

第三十关:

使用指针来引用数组,可以提高目标程序质量(占内存少,运行速度快)。

main()

{

int a[10];

int *p,i;

for(i=0;i<10;i++)

scanf(“%d”,&a[i]);

printf(“\n”);

for(p=a;p<(a+10);p++)

printf(“%d”,*p);

}

此程序会提高程序运行效率,因为像p++这样的指针操作是比较快的。

数据名是数组首元素的地址,它是一个指针常量。它的值在程序运行期间是不变的。

第三十一关:

当在形参中要引用一个数组时,往往C语言专业人员喜欢用指针变量做形参。如,专业人员

更喜欢f(int *arr,int n);

不太喜欢f(int arr[], int n);

第三十二关:

对于int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};

a[0],a[1],a[2],每一个元素又是一个一维数组。

a+1代表第一行的首地址,而a+1就代表第二行的首地址。

*(a[i]+j)和*(*(a+i)+j)是二维数组元素a[i][j]的值。

a和a[0]的值虽然相同,但其指针类型不同,a指向一维数组,a[0]指向a[0][0].

第三十三关:

int (*p)[4],p是一个指针变量,它指向包含4个整型元素的一维数组。注意*p两侧的括号不能缺少,因为[]的优先级高于*,所以如果写成*p[4],那就变成了*(p[4]),这个表示一个含有4个元素的一维数组,其中每个元素都是一个指针变量。

第三十四关:

用字符指针做形参来实现字符串的复制:

void copy_string(char *from, char *to)

{

for(;*from!=’\0′;from++,to++) *to=*from;

*to=’\0′;

}

此代码可以改进为:

void copy_string(char *from,char *to)

{

while((*to++=*from++)!=’\0′);

}

此代码还可以改进,由于’\0’可以用0代替,且条件里0即代表假,所以代码可修改为:

void copy_string(char *from,char *to)

{

while(*to++=*from++);

}

对于C语言熟练之后,这种形式的使用是非常多的,读者应该逐渐熟悉它,掌握它。

over~

1条评论

发表您的评论

请您放心,您的信息会被严格保密。必填项已标识 *