作者按:虽然了解以下的知识对于你的编程能力基本不会有什么提高,但我们希望体现的是研究一门学问时的细心和专注。作为程序设计的入门语言C,如果你在学习时能很留意这些细节的知识点,那么可以预测你在将来漫长的计算机学习过程中也会很顺利的。
1. 关于条件表达式。形如:逻辑表达式? 表达式1 : 表达式2。
逻辑表达式的值若为非零(真),则条件表达式的值等于表达式1,若逻辑表达值的值为零(假),则条件表达式的值等于表达式2的值。特别要注意的是条件表达式的结合方向是从右向左结合的。
例:与 y=(x>0?1:x<0?-1:0);的功能相同的if语句是:
if(x>0) y=1;
else if(x<0)y=-1;
else y=0;
解:y=(x>0?1:x<0?-1:0)与y=(x>0?1:(x<0?-1:0))等价。
2. 关于赋值表达式,将赋值号"="右侧表达式的值赋给赋值号左边的变量。赋值表达式的值为执行赋值后被赋值的变量的值。形如a=b ,b会被转换为符合a的类型,如果不能转换,要么报警告,要么报错。赋值表达式也是从右向左结合的。
例:下列选项中,不正确的赋值语句是__C__
A) ++t B) n1=(n2=(n3=0))
C)k=1=j D) a=b+c=1
解:C选项里先执行的是右结合的1=j显然错误,注意B选项是以赋值表达式赋值,是正确的,其整个表达式最终的值是0。
3. 关于逗号表达式,顺序求(表达式1,表达式2……表达式n)的值,则整个表达式的类型和值都为表达式n的值。
例:设有以下定义:
main()
{
int x=10,y=3,z;
printf("%d\n",z=(x%y,x/y));
}
输出结果是__3__
4. 关于实型表达式,只要表达式中有一个运算量是实型(float或double),运算过程中所有的运算量都要转换为double型,表达式的结果也为实型。其余类似,即往宽的地方转换。如果两个整形值相除,其结果被截尾取整,如果该操作数是负数,则截断的方向并无规定。
例:若已定义X和Y为double型,则表达式:x=1,y=x+3/2的值是__C__
A) 1 B) 2
C) 2.0 D)2.5
解:
'/'的优先级较高,所以先算3/2,这是两个整形相除,结果是1,而不是1.5。然后算x+1,因为x是double型,所以整形的运算量1要转换为double型,最终结果为double型。
5. 形如a+=x的表达式的等价于a=a+x 。
例:设int a=12,则执行完语句a+=a-=a*a后,a的值是__-264___
解:赋值表达式的结合顺序是从右向左结合的。
先执行 a-=a*a ,即 a=a-a*a,在这一步时 a=12-12*12,即a=-132
再执行 a+= , 即 a=a+a,在这一步时 a=-132+(-132),所以a=-264
6. 常用字符ASCII码:'0'——48, '9'——57, 'A'——65, 'a'——97, '\0'或'\000'——0(代表空操作字符,同时也是字符串的结束标记),小写字母比大写字母的ASCII码大,两者相差32。
例:若有以下定义和语句:
char c1='b',c2='e';
printf("%d,%c\n",c2-c1,c2-'a'+'A');
则输出结果是___B___
A) 2,M B) 3,E
C) 2,e D) 输出结果不确定
7. a++就是将a的值先用作表达式的值,然后a的值再加1,++a是先将a的值加1,然后再将a的值作为表达式的值。
例1:main()
{
int a=10;
int i;
i=a++ + ++a + a++ + ++a;
printf("i=%d,a=%d\n",i,a);
}
问i=多少,a=多少?
解:这题的答案是不确定的,a=14,但i根据编译器的不同或者等于45,或者等于48。
例2:
两次运行下面的程序,如果从键盘上分别输入6和4,则输出结果是__7 和5__
main()
{
int x;
scanf("%d",&x);
if(x++>5)
printf("%d",x);
else
printf("%d\n",x--);
}
8. 各类运算符的优先级别:详细请看谭老的《C程序设计(第二版)》的P375页。
初等运算符(括号加结构体运算符)>
单目运算符(注意逻辑非运算符! 它是除初等运算符外具有最高优先级别的)>
算术运算符(先乘除模,后加减,再移位)>
关系运算符>
逻辑运算符(&& ,|| ,不包括 ! )>
条件运算符(唯一一个三目运算符,即 ? : )>
赋值运算符>
逗号运算符>(即顺序求值运算符)
例:以下十个运算符+ ! << != , ?: && = || %中优先级别最高和最低的分别是____!____和____,____。
9. static的作用。
l 一是其声明的局部变量为静态局部变量,静态局部变量的值在程序整个运行期间不释放,即下次调用该函数时其值仍保留;其如果在编译时赋初值的,只赋值一次;不赋初值的,编译器自动赋值为0(数字型)或空字符(字符型);虽然静态局部变量在函数调用结束后仍存放,但外部的程序仍然不能引用。
l 二是其声明的外部变量为静态外部变量,只能用于本文件,即使其他文件用了extern仍不能引用。
10. 十进制(一般的数字序列),八进制(以0开头的数字序列,字符用'\ddd'赋值),十六进制(以0x开头的数字序列,字符用'\xhh'赋值)。另外1.5e-2表示1.5*10-2或者0.015。
例:设有以下语句:
char c;
c='\x1C';
则C的二进制的值是__C__
A) 00011011 B) 00010100
C) 00011100 D) 00011000
解:
c='\x1C';是指以十六进制的形式给字符c赋值,其相当于c='28';所以转换为二进制即11100。
11. 定义结构体与typedef的代码:
struct people // people是结构体名
{
char name[10]; // 成员列表
int age;
float height;
double weight;
}; // 分号千万不能漏
typedef struct people SP; // 用typedef方式定义新的类型名SP,方便些
//-------------------------------------------------------------------------------------------------
// 也可以写成这样
typedef struct people
{
char name[10];
int age;
float height;
double weight;
}SP;
12. 判别几个容易混淆语句的异同。异同都在我的脑海里,懒得打出来了,希望你自己想想,然后可以印在你脑海里。
break与continue
while,do……while与for
if……else if……else……与switch……case……default
define与typedef
13. int *p[4]与int (*p)[4]的异同。
l int *p[4]表示p是指针数组。由于[]比*优先级高,因此p先与[4]结合,形成p[4]形式,这显然是数组形式,它有4个元素。然后再与p前面的“*”结合,“*”表示此数组是指针类型的,每个数组元素(相当于一个指针变量)都可指向一个整型变量。
l int (*p)[4]表示p是一个指针变量。它有4个元素,每个元素为整型。也就是p所指的对象是有4个整型元素的数组,即p是行指针。应该记住,此时p只能指向一个包含4个元素的一维数组,p的值就是该一维数组的首地址。p不能指向一维数组中的第j个元素。
14. *p++与*(++p),*(p++)与*(++p),还有 (*p)++
l *p++与*(++p)作用不同。前者是先取*p值,后使p的指针值加1。后者是先使p的指针值加1,再取*p值。
l 若p初值为a(即&a[0]),输出*(p++)时,得a[0]的值,而输出*(++p),则得到a[1]的值。
l (*p)++表示p所指向的元素值加1,即(a[0])++,如果a[0]=3,则(a[0])++的值为4。注意:是元素值加1,而不是指针值加1。
15. 若有定义int a[size][size];
l 请记住*(a+i)和a[ i ]是等价的。
l *(a[ i ]+j)、*(*(a+i)+j)都是二维数组元素a[ i ][j]的值。有人可能会问“a+1的值和a+1的地址怎么会是一样的呢”?其实,a+1是地址(指向第1行首地址),而*(a+1)并不是“a+1单元的内容(值)”,因为a+1并不是一个实际变量,也就谈不上它的内容。*(a+1)就是a[1],而a[1]是一维数组名,所以也是地址。以上各种形式都是地址计算的不同表示。
l a,a[0]的值虽然相同,但是由于指针的类型不同(a是指向一维数组,a[0]指向a[0][0]元素)因此,对这些指针进行加1的运算,得到的结果是不同的。 请记住,二维数组名(如a)是指向行的。因此a+1中的“1”代表一行中全部元素所占的字节数。一维数组名(如a[0],a[1])是指向列元素的。a[0]+1中的“1”代表一个元素所占的字节数。在行指针前面加一个*,就转换为列指针。例如,a和a+1是行指针,在它们前面加一个*就是*a和*(a+1) ,它们就成为列指针,分别指向a数组0行0列的元素和1行0列的元素 。反之,在列指针前面加&,就成为行指针。例如&a是指向0行0列元素的列指针。
例1:设有数据定义如下,则可以引用组中第i个元素(0<=i<=9)的表达式有(ABCD)
int a[10]={0,1,2,3,4,5,6,7,8,9},*p=a;
A、a[ i ] B、*(a+i) C、p[ i ] D、*(p+i) E、*p+i
例2:若有以下的变量说明和语句,则在语句被执行后,*(*(pt+1)+2)表示的数组元素是__D__
int t[3][3],*pt[3],k;
for(k=0;k<3;k++)
pt[k]=&t[k][0];
A) t[2][0] B) t[2][2] C) t[2][1] D) t[1][2]