Contents

这周开始做C语言笔试卷,什么嘛!考的都是概念,各种细节,虽然貌似书上都能找到,但我还真不清楚…顿时又有一种我C语言学的好渣的感觉 T_T

好了,说下在【上机实验蓝皮书背后,综合测试题二】中难到的2道题,这两道题使得你对【指针数组】和【数组指针】的区别更加清晰。

【例题1】 有以下程序:

1
2
3
4
5
6
7
8
9
#include 

int main()
{
char \*s\[\] = {"one", "two", "three"}, \*p;
p = s\[1\];
printf("%c, %s\\n",*(p+1), s\[0\]);
return 0;
}

执行后的结果是___

A. n, two B. w, one C. t, one  D. o, two

第一次我选了 C,因为我以为 (p+1) 是指向 “three“ 的。这是对指针 p 类型的理解错误。 正确答案是 B,因为:

1
2
3
4
5
6
7
8
9
10
11
 #include 

int main()
{
char *s\[\] = {"one", "two", "three"}; // s是一个指针数组,元素是3
// 个指向字符串常量的指针
char *p = s\[1\]; // p是一个指向字符串的指针变量
printf("%c, %s\\n",*(p+1), s\[0\]);
// (p+1)是p的地址加一个字符内存的大小,从指向t变成指向w
return 0;
}

所以,平时我们说的指向字符串的指针,其实都是指向一个字符,所以对它进行位移运算时,加减都是1。

另外,如果你把第8行

printf("%c, %s\\n",*(p+1), s\[0\]);

改成

printf("%c, %s\\n",*p, s\[0\]);

输出就会是:wo,one

因为平时我们输出字符串的时候,实际上都是把字符串的首地址传给 printf( ) 函数,它通过末尾的 ‘\n’,来判断是否结束。

【例题2】

1
2
3
4
5
6
7
8
9
#include 

int main()
{
int a\[3\]\[4\] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
int (*p)\[4\] = a;
printf("%d\\n", *(*(p+1)+3));
return 0;
}

以上代码执行的结果是___

答案是 8

这道题初看我完全不理解…怎么了还能,(*p)[4]又是什么鬼…我做这份卷子前把【指针数组】和【数组指针】搞乱了=

是这样的:

1.(*p)[4]:声明p是一个指向(4个int元素的数组)的指针,因此 p+1 从指向 a[0],变成指向 a[1]

2.((p+1)+3):为什么会有两个星?

*(p+1) => a[1][0](也就是5),第一星从a[1]变成a[1][0],这个过程虽然地址没有变,但指针的类型变了!原来指针+1是加4个 int,现在指针+1只加一个 int 了!!

(p+1)+3 => a[1][3](也就是8),再取一个就是从地址里读出8

还可以修改一下原来的代码弄清楚:

1
2
3
4
5
6
7
8
9
10
11
12
13
 #include 

int main()
{
int a\[3\]\[4\] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
int (*p)\[4\] = a;
printf("p: %p\\n",p);
printf("p+1: %p\\n",p+1);
printf("*(p+1): %p\\n",*(p+1));
printf("*(p+1)+3: %p\\n",*(p+1)+3);
printf("%d\\n",*(*(p+1)+3));
return 0;
}

输出的结果是:

p: 0x7fff9f4ba180

p+1: 0x7fff9f4ba190

*(p+1): 0x7fff9f4ba190

*(p+1)+3: 0x7fff9f4ba19c

8

好啦~ 这篇笔记最早发在博客园里,直接粘贴过来再排版的,所以格式不太美观,可以看→原文

Contents