c语言指针简述
1、变量
1
2
3
4
5
6
7
8
9
int main()
{
int val1 = 100;
printf("address : 0x%x\n",&val1);
printf("size : %d\n",sizeof(val1));
printf("value : %d\n",val1);
return 0;
}
1
2
3
4
输出结果:
address : 0x61fe1c
size : 4
value : 100
1、变量为在一个内存区域开辟一个变量大小的空间,空间内用来存放变量的值
2、数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
int val2[10] = {1, 2, 3, 4, 5, 6, 7};
printf("address : 0x%x & 0x%x\n", &val2, val2);
printf("size : %d=%d*%d\n", sizeof(val2), sizeof(val2[0]),
sizeof(val2) / sizeof(val2[0]));
printf("value : ");
for(int i = 0; i < 10; i++)
{
printf("%d, ",val2[i]);
}
return 0;
}
1
2
3
4
输出结果:
address : 0x61fdf0 & 0x61fdf0
size : 40=4*10
value : 1, 2, 3, 4, 5, 6, 7, 0, 0, 0,
1、数组为在内存区域开辟一个(变量大小*数量)的空间,空间内用来存放变量的值。
2、数组名表示的为变量的起始地址,
&val2 == val2
,同指针,指向的内容为起始地址。3、变量(数组)名不是可修改的左值,固定指向开辟的该空间的起始地址。
4、数组进行加减处理,为数组的起始地址进行加减 (类型大小 * 数量) 偏移,如
val2+2 == 0x61fdf8
,这里同指针。
3、指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
int val2[10] = {-136463, 2, 3, 4, 5, 6, 7};
int *val3 = val2;
char *val4 = (char *)val2;
printf("address : 0x%x\n", &val3);
printf("size : %d\n", sizeof(val3));
printf("value : 0x%x\n", val3);
printf("*val : %d\n", *val3);
printf("address : 0x%x, *val : %d\n", val3 + 2, *(val3 + 2));
printf("val4 : 0x%x\n", val4);
printf("*val4 : %02x = %d\n", (unsigned char)(*val4),*val4);
return 0;
}
1
2
3
4
5
6
7
8
输出结果:
address : 0x61fde8
size : 8
value : 0x61fdf0
*val : -136463
address : 0x61fdf8, *val : 3
val4 : 0x61fdf0
*val4 : f1 = -15
1、指针为在内存区域开辟一个指针变量大小的空间,在64位系统,所有的指针类型大小固定为8bytes,空间内用来存放指向的地址。
2、指针变量的值为指向空间的地址,是可修改的左值,可以指向任意想指向的空间。
3、对指针变量进行解引用(*)可以获取到指向地址的值,解引用的方式根据指针类型来。
4、对指针进行加减处理,为指针指向的地址进行加减 (类型大小 * 数量) 偏移,进行解引用可以获取偏移地址的值。
5、指针可以指向任何地址,对指向地址的内容进行读取及修改与指针类型相关。
4、函数
1
2
3
4
5
6
7
8
9
10
11
12
int fun_add(int a, int b)
{
return a + b;
}
int main()
{
printf("address : 0x%x\n", fun_add);
printf("size : %d\n", sizeof(fun_add));
printf("running : %d\n",fun_add(4,7));
return 0;
}
1
2
3
4
输出结果:
address : 0x401550
size : 1
running : 11
1、函数为在代码区(不同于前面的变量区)的一个位置,大小为一个字节,它表示编译完成函数在这个位置。
5、函数指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int fun_add(int a, int b)
{
return a + b;
}
int fun_sub(int a, int b)
{
return a - b;
}
typedef int (*fun_type)(int, int);
int main()
{
int (*p_fun)(int, int) = fun_add;
fun_type p_fun2 = fun_div;
printf("address : 0x%x & 0x%x\n", &p_fun, &p_fun2);
printf("size : %d & %d\n", sizeof(p_fun), sizeof(p_fun2));
printf("value : 0x%x & 0x%x\n", p_fun, p_fun2);
printf("running : %d & %d\n", p_fun(4, 7), p_fun2(8, 2));
return 0;
}
1
2
3
4
5
输出结果:
address : 0x61fe08 & 0x61fe00
size : 8 & 8
value : 0x401550 & 0x401589
running : 11 & 4
1、函数指针的内存分配和大小与普通指针一致,格式需要与指向的函数一致(入口参数,返回类型)
2、可以使用typedef对函数指针类型更改名称,在定义函数指针变量的时候会变的简洁一些,效果与普通函数指针一样。
3、函数指针的内容为指向函数的地址,对函数指针进行解引用的方式为“按照函数格式进行使用”
6、指针数组
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
int g_val1[4][2] = {/**/ {1, 2}, {3, 4}, {5, 6}, {7, 8} /**/};
int g_val2[4]={10,11,12,13};
int g_val3[10]={100,101,102,103,104,105,106,107,108};
int main(int argc, char **argv)
{
// int *p_val[4] = {g_val1[0], g_val1[1], g_val1[2], g_val1[3]};
int *p_val[4] = {0};
p_val[0] = g_val1[0];
p_val[1] = g_val1[1];
p_val[2] = g_val1[2];
p_val[3] = g_val1[3];
for (int i = 0; i < 4; i++)
{
printf("addr:%x, value:%d,%d\n", p_val[i], p_val[i][0], p_val[i][1]);
}
p_val[0] = g_val2;
p_val[1] = g_val3;
printf("address:%x\n", p_val[0]);
for (int i = 0; i < 4; i++)
{
printf("%d, ", p_val[0][i]);
}
printf("\n");
printf("address:%x\n", p_val[1]);
for (int i = 0; i < 10; i++)
{
printf("%d, ", p_val[1][i]);
}
return 0;
}
1
2
3
4
5
6
7
8
9
输出结果:
addr:403020, value:1,2
addr:403028, value:3,4
addr:403030, value:5,6
addr:403038, value:7,8
address:403040
10, 11, 12, 13,
address:403060
100, 101, 102, 103, 104, 105, 106, 107, 108, 0,
1、指针数组为指针的一个集合,如int型数组为int型数据的一个集合,它里面都是设定类型的指针。
2、指针数组每个元素存放一个指针变量,指针变量可以指向任意长度的数组,指向数组的首地址。
7、数组指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int g_val1[4][4] = {/**/{1, 2}, {3, 4}, {5, 6}, {7, 8}/**/};
int g_val3[10]={100,101,102,103,104,105,106,107,108};
int main(int argc, char **argv)
{
int (*p_val)[4]=NULL;
p_val = g_val1;
printf("address:%x\n", p_val);
for (int i = 0; i < 4; i++)
{
printf("%d, ", p_val[0][i]);
}
printf("\n");
// error: assignment to 'int (*)[4]' from incompatible pointer type 'int *'
// p_val=g_val3;
// printf("address:%x\n", p_val);
return 0;
}
1
2
3
输出结果:
address:403020
1, 2, 0, 0,
1、数组指针是指针,指向一个次维有n个元素的数组,指向数组的整体,这里指向二维数组,且第二维有4个元素,同数组指针的类型。
2、数组指针本质上是一个指针,不能像“指针数组”一样进行切片处理。
8、二者对比
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
int g_val1[4][4] = {/**/{1, 2}, {3, 4}, {5, 6}, {7, 8}/**/};
int main(int argc, char **argv)
{
int (*p_val)[4]=g_val1;
int *p_val2[4] = {g_val1[0], g_val1[1], g_val1[2], g_val1[3]};
printf("address:%x\n", g_val1);
printf("address:%x\n", p_val);
printf("address:%x\n", p_val2);
printf("\n");
for (int i = 0; i < 4; i++)
{
printf("%x, %x\n", p_val+i, p_val2+i);
}
printf("\n");
for (int i = 0; i < 4; i++)
{
printf("%x, %x\n", p_val[i], p_val2[i]);
}
printf("\n");
for (int i = 0; i < 4; i++)
{
printf("%d, %d\n", p_val[i][0], p_val2[i][0]);
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
输出结果:
address:403020
address:403020
address:61fde0
403020, 61fde0
403030, 61fde8
403040, 61fdf0
403050, 61fdf8
403020, 403020
403030, 403030
403040, 403040
403050, 403050
1, 1
3, 3
5, 5
7, 7
1、对于初始化赋值,数组指针可以直接指向二维数组,而指针数组需要对每一个数组元素进行赋值。
2、数组指针的值就是指向目标的地址,而指针数组的值为自己本身这个数组的地址。
3、对数组指针进行加减处理,偏移的地址是以n个数据为偏差的,而指针数组的偏差地址是以指针大小为偏差的。
4、对二者进行解引用,指向的都是二维数组的每一行,当然数组指针是仅知道首地址,根据自己的类型进行往后偏移的,而指针数组为手动将每一行的值给上的。
5、二者进行两次解引用都差不多。