数组与指针笔记

程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
#include <stdlib.h>

void
f(void)
{
int a[4];
int *b = malloc(16);
int *c;
int i;

printf("1: a = %p, b = %p, c = %p\n", a, b, c);

c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);

c[1] = 300;
*(c + 2) = 301;
3[c] = 302; /* c 语言数组名和下标可以互换,c[3] 和 3[c] 是一样的*/
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);

c = c + 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);

c = (int *) ((char *) c + 1);
*c = 500;
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
/*
int 占 4 个字节,char 占 1 个字节,c 所指的 int 原来是 400,((char *) c + 1) 以后指向第二个字节,(int *) ((char *) c + 1)后
占据原来 a[1] 的高 3 字节和 a[2] 的低 1 字节,*c = 500 以后,a[1] 的高 3 字节存储了 500, a[1] 的低 1 字节保留原来 301 的单字节
部分, a[2] 的低 1 字节被置 0 .
*/

b = (int *) a + 1;
c = (int *) ((char *) a + 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}

int
main(int ac, char **av)
{
f();
return 0;
}

《c和指针》部分抄录

1
以下是《c和指针》关于指针的指针的部分抄录:

假设:
int a = 12;
int *b = &a;
int **c = &b;
他们在内存中的模样大概是:

利用上述中间的一级指针可以编写代码输出内存内容:

1
2
3
void** addr = (void**) begin;
for (i = 0; i < n; ++i)
printf("VM at %x is %x\n", addr+i, addr[i]);

上述设计思想是:指针所加内容是指针存储的地址,所加范围是由指针指向的对象类型决定。因此,二级指针addr+i所加内容是二级指针存储的一级指针地址,所加范围是由二级指针所指向的一级指针决定,此处一级指针是void ,即每次加4个字节(若是有二级指针&a是指向一个有5个整型元素的数组的地址,&a+1就是从a向后跳过一个完整的数组所占用的内存空间)。addr[i]是`(addr+i)`,即一级指针的内容。因此,这里是将内存内容当作一级指针内容看待!

假设:
char ch = ‘a’;
char cp = &ch;
1、
*++cp: 间接访问操作符作用于增值后的指针的拷贝上,所以它的右值是ch后面那个内存地址的值,而它的左值就是那个位置本身。

2.*cp++: 使用后缀++操作符的右值和左值分别是变量ch的值和ch的内存位置,也就是cp原先所指。同样,后缀++操作符在周围的表达式中使用其原先操作数的值。后缀++操作符的优先级高于*操作符,但表达式的结果看上去像是先执行间接访问操作。事实上这里涉及三个步骤:(1)++操作符产生cp的一份拷贝,(2)然后++操作符增加cp的值,(3)最后在cp的拷贝上执行间接访问操作。这个表达式常常在循环中出现,首先用一个数组的地址初始化指针,然后使用这种表达式就可以依次访问该数组的内容了。

3.++*cp: 由于这两个操作符的结合性都是从右往左,所以首先执行的是间接访问操作。然后cp所指向的位置的值增加1,表达式的结果是这个增值后的值的一份拷贝。

4.(*cp)++: 使用后缀++操作符,我们必须加上括号,使它首先执行间接访问操作,这个表达式的计算过程与前一个表达式相似,但结果值是ch增值前的原先值。

记住两个结论:1、++优先级大于*; 2、后缀++始终返回一份拷贝(可能是指针拷贝)。

显示 Gitment 评论