指针的本质就是地址
#include <stdio.h>
// 指针
int main()
{
int i = 5;
// &是(引用)取地址 指针变量的初始化一定是某个变量取地址
int *i_pointer = &i;
// || *是解析地址 如果只是 i_pointer 就是其存的地址
printf("%d\n", *i_pointer);
return 0;
}
指针传递
#include <stdio.h>
void change(int *j) // j 形参 j=&i
{
*j = 5;
}
// 指针传递
int main()
{
int i = 10; // i 局部变量
printf("before change , i = %d\n", i);
change(&i); //函数调用时,把&i称为实参
printf("after change , i = %d\n", i);
return 0;
}
指针偏移
前面介绍了指针的传递。指针即地址,就像我们找到了-栋楼,这栋楼的楼号是B,那么往
前就是A,往后就是C,所以应用指针的另一个场景就是对其进行加减,但对指针进行乘除是没
有意义的,就像家庭地址乘以5没有意义那样。在工作中,我们把对指针的加减称为指针的偏移,
加就是向后偏移,减就是向前偏移。
#include <stdio.h>
// 指针偏移
int main()
{
int a[5] = {1,
2,
3,
4,
5};
int *p; //对一个指针变量进行取值,得到的类型是其基类型
p = a;
for (int i = 0; i < 5; i++)
{
/* 先偏移在取地址 */
printf("*p = %d \n", *(p + i));
}
return 0;
}
指针自增自减
#include <stdio.h>
// p[0] = *p
// 指针自增
int main()
{
int a[3] = {2, 5, 8};
int *p;
int j;
p = a; // 让指针变量p,指向数组的开头
// j = *p++;
j = *p;
p++;
printf("a[0] =%d,j =%d,*p =%d\n", a[0], j, *p); // 2,2,5
// j = p[0]++;
j = *p;
printf("之前的*p =%d\n", *p);
printf("之前的a[1] =%d\n", a[1]);
// *p++ 指的是这个空间向前加一位 (*p)++ == p[0]++这个地址里面的数加一
*p++;
printf("之后的*p =%d\n", *p);
printf("之后的a[1] =%d\n", a[1]);
printf("a[1] =%d,j =%d,*p =%d\n", a[1], j, *p); // 6,5,6
return 0;
}
指针与一维数组
一维 数组在函数调用进行传递时,它的长度子函数无法知道
数组名作为实参传递给子函数时,是弱化为指针的
#include <stdio.h>
void change(char *d)
{
*d = 'H';
d[1] = 'E';
// 等于上面的操作
// *(d + 1) = 'E';
*(d + 2) = 'L';
}
// 指针与一维数组
int main()
{
char c[10] = "hello";
change(c);
puts(c);
return 0;
}
指针与动态内存申请
C语言的数组后会觉得数组长度固定很不方便,其实C语言的数组长度固定是因为其定义的整型、浮点型、字符型变量、数组变量都在栈空间中,而栈空间的大小在编译时是确定的。如果使用的空间大小不确定,那么就要使用堆空间。
程序是放在磁盘上的有序的指令集合