理论考个人错题整理
1.typedef题型
(1)用typedef写出类型POINT的定义,使得POINT表示指向由10个字符指针构成的数组的指针类型
//这题很绕,首先先明确POINT是个数组指针,即(*POINT)[10],而该数组指针指向的数组每个元素的变量类型为字符指针,故char * (*POINT)[10],最后再套上typedef
typedef char * (*POINT)[10];
(2)已知一个函数指针类型,它所指的函数返回值类型为空类型,接受两个参数,一个是字符指针类型,一个是整型。用typedef将该函数指针命名为FunType
先写出定义时函数指针类型(要记住),再套上typedef
void (*FunType)(char *,int );
typedef void (*FunType)(char *,int );
2.数组的部分初始化
(1)假设一个指针变量变量8个字节,则以下程序运行结果
int f(long a[])
{
return (int)sizeof(a);
}
void main()
{
long a[][3]={1,2,3,4},*p;
printf("%d#%d\n",sizeof(a),f(a[0]));
}
二维数组部分初始化时,{1,2,3}被放在了第一行,{4}被放在第二行,没有被初始化的元素初始值被赋为0。所以该二维数组一共2行3列,共6个元素,每个元素类型为long,4字节,所以sizeof(a)等于24
a[0]为a[0] [0]的地址,为一个指针类型,所以返回值为8
(2)求sizeof(s)
char s[80]={"apple\0grape\0pear\0coco\0"};
字符串数组初始化时,未被初始化的元素都会直接赋值为'\0',而sizeof是统计整个s的,不是遇到'\0'就停下来,所以返回80
需要注意的是strlen(s)是不计入'\0'元素的,并且到了第一个'\0'元素就停下了
(3)二维数组定义时,行号可以省略,列号不可以省略
3.字符串的'\0'
做题建议:补充所有字符串被省略的'\0'
(1)求下列字符串常量的字符个数
"zju\101\\TED"
\101表示八进制的字符串常量,101为八进制的ascii码值
\ \表示单个反斜杠,第一个反斜杠是转义符
但是字符串结尾最后一定有的'\0'不能忘记!
(2)
char p[3][4]={"ABC","DEF","XYZ"};
char *q[3]={p[0],p[1],p[2]};
*(*(q+1)-1)=*p[2];
puts(*p);
//puts输出字符串时,直到'\0'才停下。q是一个指针数组,每个元素存放一个字符串的地址。q+1指向"DEF"的地址,解引用后得到'D'的地址,这时再-1,指向的是ABC后面'\0'的地址,然后再解引用,赋值成*p[2],即'X',所以p现在实际存放值为{"ABCX","DEF\0","XYZ"},故最后输出结果为ABCXDEF。
4.逻辑表达式
(1)-6<=x<=-2与x>=-6 && x<=-2不等价,千万别被骗,-6<=2的返回值不是0就是1,一定大于-2,所以该表达式恒为0
(2)字符串指针非空为真,空为假
(3)'\0'代表ascll码0,值为假;'0'代表ascll码48,值为真
5、数组、指针和结构
int a[10]; //数组
int *a[5]; //指针数组,数组的每个元素类型是int*
int (*a)[5]; //数组指针,a是一个指针,指向一个int [5]的数组
int *a();//a是一个函数,返回值为int *类型
int (*a)(char*);//a是一个函数的指针,指向的函数返回值为int,参数类型为char*
(1)
int p[5],*a[5];
下列表达式正确的是( )
A. p=a
B. p[0]=a
C. *(a+1)=p;
D. a[0]=2;
//A,数组是指针常量,不能直接赋值
//B.p[0]类型应该是int,但是a代表的是a[0]的地址,而a[0]类型为int *,故a类型可以理解为int **
//C.*(a+1)=*(&a[0]+1)=*(&a[1])=a[1],类型为int *,而p数组代表的是首元素的地址,类型是int *,类型对应,赋值成功
//D.a[0]类型为int *,类型不匹配
(2)
求z的值
static struct{
int x,y[3];
}a[3]={{1,2,3,4},{5,6,7,8},{9,10,11,12}},*p=&a[-1];
int z;
z=*((int *)(++p+1)-1));
//先执行++p,将p指向a[0],再加1,将p指向a[1],然后强制转化为int *类型(原来类型为 struct *),此时再减1,p指向a[1]首元素地址-1的位置,即4这个元素,最后解引用,得4。
(3)
下列赋值正确的是
struct node{
char s[10];
int k;
struct node *next;
}p[5],*q=p;
//q.k=2; q是指针,不能直接用.运算符
//p[0]->k=2; p[0]是一个struct变量,不能用->运算符
//(p->s)[0]='a'; 正确
//q->s="a"; 字符串是指针常量,不能直接赋值
(4)
struct{
int k;
char s[30];
}a[5]={1,"ABC",2,"abc"},*p=a;
求表达式*(p++)->s的值
//p++返回p,箭头运算符优先级高,返回“ABC”,可以理解为首元素的地址,最后解引用得'A'
(5)
short a[10],*p=a+5;
求(char* p)-(char *)a的值
//p-a的计算公式为((int)p-(int)a)/sizeof(*p),一个short类型字节为2,原来指针p与a相差10个地址,转化为char*后,计算时分母的类型为char,即1字节,所以值为10
(6)
struct H{
int k;
char *s;
}a={1,"Wang"},*p=&a;
计算下列输出结果:
*p->s++;
printf("%s",++a.s);
//->优先级最高,p->s为"Wang"首元素的地址,而*与++同级,且这两者是右结合性,所以先s++,虽然返回s值,但是s的指针已经到了s[1]的地址上。然后访问a.s,此时s是s[1]的地址,再做++,返回s+1的值,固s最后指向s[2]的地址,所以最后输出"ng"。
(7)
若有函数声明void f(char **p),则下列调用f(var)不正确的是
//char var[10][10],二维数组不能理解为二级指针,只能理解为数组指针,类型不对应
//char *var[10],此为指针数组,也可以理解为首元素的指针,首元素的类型为char *,固var可以理解为char **
//void *var=NULL; void*类型可以理解为指向任意类型的指针,令该类型为char *,则var类型为char **
//char *v=NULL,**var=&v; var类型为char **