C语⾔指针经典练习题
1、指针,字符数组
若定义
1. char s[2][3]={“ab”, “cd”}, *p=(char *)s;
那么下列表达式语法正确,并且其值与 s[1][1]相等的表达式(并⾮⼀定与其等价)是
A. *(s+3)
B. p[1][1]
C. *(p+3)
D. *++P+2
答案:D
分析:这道题很好。⾸先字符型指针p存放的是字符串s的⾸地址,⽽字符串s表⽰的是这样⼀个字符串:
ab_
cd_
为了便于理解,“_”表⽰空格,即没有元素。题中s[1][1]是d,所以要在ABCD中寻表⽰s[1][1]的数。
先来看*(s+3),s表⽰数组⾸地址,不是指针型变量,所以s+3没有意义。p[1][1]同样由于p是指针,不存在这种表达。*(p+3)是是p表⽰的指针后移3位,因此*(p+3)是c。D选项有点复杂,*++p+2 这个⽐较有趣,p是⼀个char*指针,指向字符数组⾸地址,&s[0][0]。⾸先++的优先级更⾼执⾏++p得到的是&s[0][1],然后*运算符解引⽤,得到s[0][1],s[0][1]的字符是'b',然后'b'+2,得到的就是'd'的ASCII码.
下⾯是⼀道类似的题⽬:
若定义 char a[3][3]={“ad”, “ce” , “fb”}, *s = (char *)a; 那么下列表达式语法正确,并且其值与 a[2][1]相等的表达式是
_______。
A.*(a+3) B.*(*a+5) C.s[2][1] D.*++s-2
18、指针的指针
有函数原型为
1. void f(int, int *);
,主函数中有变量定义:
1. int a=2, *p=&a;
则下列函数调⽤正确的是
A. f(a,&p);
B. f(*p, p);
C. f(p,a);
D. f(*p, a);
答案:B
分析:注意p为指向整型的指针,*p则指向内存地址处所存放的数据。*p实际上就是a.
22、宏定义
下列程序段的输出是_______。
#define DF(a,b)  (a+2*b)
int s=5;
int k= DF(s+1,s-3);
printf("%d",k);
答案:13
分析:k=DF(5+1,5-3)=5+1+2*5-3=13。注意宏定义中参数的传递,k=DF(5+1,5-3)=(5+1)+2*(5-3)=10是错误的。
23、全局变量、局部变量、静态变量的⽣存期
以下代码的输出是:
int x, y, z, w;
void p(int *y, int x)
{
static int w;
*y++; x++; w = x+*--y;
printf("%d#%d#%d#%d#",x,*y,z,w);
}
int main(void)
{
int x, y, z, w;
x=y=z=w=1;
do{
static int x;
p(&x, y);
printf("%d#%d#%d#%d#",x,y,z,w);
} while(0);
return 0;
}
答案:2#0#0#2#0#1#1#1#
解析:主要考察局部变量和全局变量的⽣存期,以及静态本地变量。注释后的代码如下:
int x, y, z, w;    //这⾥是全局变量,定义在任何函数的外⾯,若不初始化赋值,则均为0;。注意,主函数⾥⾯的变量仍为局部变量
void p(int *y, int x)    //p函数接收整型指针变量和整型变量的输⼊,返回值为空
{
static int w;    //定义静态变量w,若不初始化赋值,则w==0;
*y++; x++; w = x+*--y;
printf("%d#%d#%d#%d#",x,*y,z,w);
}
int main(void)
{
int x, y, z, w;
x=y=z=w=1;
do{
static int x;
p(&x, y);
printf("%d#%d#%d#%d#",x,y,z,w);
} while(0);
return 0;
}
从主函数进⾏分析,主函数内部定义了四个int型变量,若不进⾏初始化,则全为0。主函数内部定义完之后就进⾏了初始化,均初始化为1,所以在do-while内部,可以看到由于只定义了静态局部变量x,⽽且没有初始化赋值,则静态局部变量x为0,y,z,w均仍为1。所以
printf("%d#%d#%d#%d#",x,y,z,w);
的输出是0#1#1#1#。
再来分析p这个函数:
void p(int *y, int x)    //p函数接收整型指针变量和整型变量的输⼊,返回值为空
{
static int w;    //定义静态变量w,若不初始化赋值,则w==0;
*y++; x++; w = x+*--y;
printf("%d#%d#%d#%d#",x,*y,z,w);
}
⾸先p函数⽆返回值,接受两个输⼊:int型指针变量、int型变量。p函数内部同样定义了⼀个静态局部变量w,但是w后⾯有赋值的语句
w = x+*--y;
*y++和x++是两个关键,⾸先*和++,--运算符处于同⼀优先级,结合⽅向是⾃右向左。因此*y++可以看做是*(y++),但是由于y++是先执⾏y,跳出去与*结合,再让y++。所以*y++实际上等效于先执⾏*y操作,再执⾏y++。由于y是指针,因此y++是指针所指内存地址的向后移动,移动的⼤⼩是⼀个sizeof(int)。x++同理先执⾏x(由于没有任何操作,x不变),再让x+1,这⾥实际上由于x没有任何操作,x++相当于只执⾏了x+1,由于局部变量传⼊p函数的x为1,这⾥x就等于2了。
由于y是指针变量,因此*y表⽰取出指针所指内存地址的值。由于传进去的
static int x;
p(&x, y);
x是静态变量,则x=0,因此*y=0。这⾥要注意p的原型是void p(int *y, int x)  ,⽽使⽤p函数时,传进去的是
p(&x, y);
顺序不要搞反了。w=x+*--y,这⾥等价于w=x+*(--y),由于在上⾯的*y++,y已经执⾏了y+1,这⾥(--y)先执⾏--,再执⾏y,即先执⾏y-1,再把y-1的结果传出去。注意这⾥的-1指的是减去⼀个int型变量的内存⼤⼩。因此y还是原来的内存位置。所以*y还是取出原来指针指向内存地址的值,即还是原来的静态局部变量x,值为0。因此w=x+*--y中x=2,(*--y)等于0,所以w=2。由于p函数⾥的z只能那个接受全局变量,因此z=0,所以p函数执⾏之后打印:2#0#0#2。
24、sizeof和数组
假设sizeof(int)的值为4,对数组定义:
1. int a[3][6];
则sizeof(a[0])的值为____.
答案:24
解析:a[0]⾥⾯有a[0][0],a[0][1]……a[0][5],共6个元素,均为int,因此4*6=24.
25、条件表达式以及&&,||,!
写出表⽰“当 x 的取值在 [-10, 0]  的范围内,结果为真,否则为假”的C语⾔表达式,注意不要任何空格
答案:x>=-10&&x<=0 或 x<=0&&x>=-10 或 !(x<-10||x>0)
解析:我的答案是(x>=-10)&&(x<=0)?1:0,不如参考答案。
26、&&,||,!
若 int a = 6, b = 0, c = 3,则表达式 a && b || b - c的结果是(以1表⽰真,0表⽰假)
答案:1
27、指针、字符串和数组
以下代码段的输出是:
char a[20]="cehiknqtw";
char *s="fbla",*p;
int i, j;
for(p=s; *p; p++) {
j=0;
while (*p>=a[j] && a[j]!='\0') j++;
for(i=strlen(a); i>=j; i--) a[i+1] = a[i];
a[j]=*p;
}
printf("%s", a);
答案:abcefhiklnqtw
分析:这段代码具有⼀定的难度。⾸先a[20]是⼀个字符数组,s,p是字符型指针。s刚开始是“fbla”的⾸地址,因此*s实际上是指向f的内存地址的值,即s存放的是f的地址。
核⼼部分是for循环中的语句,
p=s; *p; p++
是将s的指针赋给p,然后逐渐后移,也就是把s字符串中的字符指针逐渐都进⾏赋值。即,p会逐渐等于f,b,l,a的地址。
while (*p>=a[j] && a[j]!='\0') j++;
这个语句的意义是在a[]中寻求⼤于*p所指的字符,当*p==f时,a[]中的h是⼤于f的,此时j==2,程序跳出while循环,进⼊内层for循环,内层for循环的意义是把j==2之后的字符都进⾏后移⼀位,为*p==f腾出位置,然后将a[2]=*p,也就是把s中的第⼀个字符填⼊a[]中。下⾯依次填⼊s中其他的字符,因此这个程序完成的任务实际上是把s中的字符按照字符间ASCII数值的⼤⼩关系填⼊a[]中。
28、宏定义
根据下⾯的定义,F0(3+4)的输出结果是_______(注意没有空格)
#define  F1(var)  printf("var=%d", var)
#define  F0(var)  F1(var * var)
答案:var=19
29、指针的指针
程序T1的代码如下,则运⾏T1  abc  bcd  cde  aed的输出结果是_______.
int main(int argc, char** argv)
{
sizeof 指针while(**argv++!='a');
printf("%s", *argv);
return 0;
}
答案:bcd
分析:
解释⼀:程序进来后,argv的内容是 T1 abc bcd cde aed
while(); 注意while循环后⾯有分号,说明printf是在循环之后才执⾏的。
**argv++相当于
1. return argv;
2. return **argv
3. argv++ (每执⾏⼀次,将会指向下⼀个字符串)
当执⾏第⼆次循环时, abc,此时**argv为'a',循环结束。在此之后,argv++指向了下⼀个字符串,也就是bcd。
解释⼆:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。