C语言学习笔记
指针
指针与基本数据类型
- 指针是什么:
指针式一种数据类型,就像int float,int装整形数据,float装浮点型数据,指针装地址数据 - 声明一个指针的形式:
int *q,*p;//这样的意义是声明一个整形指针,同理还有:
double *d;
float *f;
short *s;
- 为指针赋值:
int a = 12;
p = &a;
q = &a-1;
printf("%p,%p,%p,%p", p, &a, &p, q)
- 这样的输出结果是:
000000000062FE0C,000000000062FE0C,000000000062FE10,000000000062FE08
- 可见,p所存储的数据就是变量a的地址。
指针操作指向空间
- 对于内存的操作只有三种:读、写、取地址
int a = 12;
int *p = &a;
1、读
printf("%p,%d,%d\n", p, *p, a);
2、写
*p = 123;
printf("%p,%d,%d\n", p, *p, a);
3、取地址
printf("%p,%p,%p\n", p, &*p, &a);
return 0;
这样的输出结果是:
000000000062FE14,12,12
000000000062FE14,123,123
000000000062FE14,000000000062FE14,000000000062FE14
这里的*可以叫做内存运算符,例如p代表的是a的地址,那么*p就是p的地址里装的数据,即*p == a。对*p进行运算也就改变了a的数据。
利用指针遍历一维数组地址
- 首先先定义一个一维数组并进行地址的输出:
int a[5] = {9,7,5,3,1};
int *p = &a[0];
printf("%p,%p,%p,%p,%p\n", p, p+1, p+2, p+3, p+4);
printf("%p,%p,%p,%p,%p\n", &a[0], &a[1], &a[2], &a[3], &a[4]);
- 结果是:
000000000062FE00,000000000062FE04,000000000062FE08,000000000062FE0C,000000000062FE10
000000000062FE00,000000000062FE04,000000000062FE08,000000000062FE0C,000000000062FE10
- 由此可见p+1==a[0]+1,这其实就是下标运算的意义。
利用指针遍历一维数组数据
- 根据*内存运算符的意义,我们可以直接用循环打印出数组的各项数据:
int i;
for (i = 0 ; i < 5 ; i++)
{
printf ("%d\t", *(p+i));
}
- 一定要记得加上小括号,查看优先级表。
指针与下标运算
- 下标运算的本质:地址+[偏移量](例如a[0],a[1])
- 也就是说a[2]==p[2]
- 准确来说,下标运算,不是数组专属,只是一个运算符。数组可以用是因为它符合了下标运算符的使用条件,地址+[偏移量]。我们的指针也是完全可以的。
- 两个简单等式:*(p+2)==p[2],*(*(p+2)+3)==p[2][3]
- 下标运算的实质:前后两个值相加得到的地址所包含的数据
指针数组
- 指针数组也叫地址数组,是若干个地址数据组成的数组
int b=4,c=3,d=7,e=8,f=1;
int *a[5] = {&b,&c,&d,&e,&f};
int i;
for (i = 0 ;i <= 4 ; i++)
printf("%p,",a[i]);
- 输出结果是
000000000062FE18,000000000062FE14,000000000062FE10,000000000062FE0C,000000000062FE08,
指针数组拉链结构
int b[3] = {1,2,3};
int c[2] = {4,5};
int d[4] = {6,7,8,9};
int e[5] = {10,11,12,13,14};
int f[2] = {15,16};
int *a[5] = {&b[0],c,d,e,f};//两种写法均可
printf("%d\n",a[2]\[2]);//这是两层下标运算
- 和二维数组的访问格式是一样的,意义也是一样的。但是内存结构是不一样的,或者说本质不一样。每个小数组大小可以不同,但是数据类型必须相同。
- 可以参照以下表格理解拉链结构:
-
b c d e f a 1 4 6 10 15 2 5 7 11 16 3 8 12 9 13 14
数组指针
- 首先再次明确两个公式:
a == &a[0],&a[0]+1 == &a[1]
- &a是对于整个数组的数组类型的地址
int a[5] = {3,4,5,2,6}
int *p = &a[4];
int *(p1)[5] = &a;//这样就定义了一个一维数组指针,(*p1)[2]==a[2]
printf ("%p,%p\n",&(*p1)[2],&a[2]);
- 输出结果是
000000000062FDF8,000000000062FDF8