以字节为单位给内存做了统一的编号 ,这个编号就是地址 , 在内存当中不管你有没有存数据,它的编号从0到最大内存单元 已经编好了 , 最小单位是一个字节 ,内存以字节为单位
内存是以字节为单位开始编号, C语言当中 内存的地址我们称为指针, 内存单位地址,编号就是指针
pointer
auto int *p
指针是存地址的 .
int a = 20 ;
int *p = &a; 把a的地址存起来 在这里 &是取地址符号
一般这样写
先声明指针
int *p;
然后再存地址
p = &a;
老师的电脑所有的地址都是四个字节 为什么? 是由物理环境决定的 .从操作系统来说, 内存大小从0 开始排 ,排到最后,用不了太大的数, 四个字节就够
0 ~ 2的32次方 -1 (0~4G-1)
地址线的地址字节数是有 操作系统决定的
int arr[] = {5, 10, 15, 20, 25};
int *p = arr;
//------------输出结果是在单独执行下面代码的前提下----------------//
//printf("%d\n", *++p); // 10 指针p先自+,然后*p,最终为10
//printf("%d\n", ++*p); // 6 先*p,即arr[0]=5,然后再++,最终为6 ,并且最终 *p =6
//printf("%d\n", *p++); // 5 先执行*p 进行取值赋值, 然后再自行++这个++是指针++不是5进行++ 这段语句执行后 地址移动一个位置 最终地址 *p = 10
//printf("%d\n", (*p)++); // 5 先*p,即*p=arr[0]=5,然后进行赋值 %d 赋值后再自增最终*p=6
//printf("%d\n", *(p++)); // 5 效果等同于*p++ 先进行去取值 后再自增 地址*p移动一个位置, 最终地址*p=10
数组名可以直接当地址赋值给指针
但是这个p[i]一定要注意
二维数组的存储空间跟 一维数组基本上一样, 存储地址都是连续的.
在二维数组中如果 *(a+i)就是a[i]改变了指针的性质 加上这个 **** 好号就是一组一组的走,不加 *** 号就是一行一行一个地址一个地址的走, 这个 * 号影响指针的性质, 变为了一级指针, 指向一级数组 .
- *****号的作用就是改变指针性质
把二维数组赋值给一级指针会出警告,意思是意思不匹配 不兼容的指针类型
这个这段代码当中,
p+1的意思是内存往下走一位,
而a+1的意思是内存往下走一组,有第一个数组切换到下一个数组
a 到 a+1 一共8个字节 两个int数
a[0] 到 a[0]+1 四个字节 一个int数
数组名就是行地址, 也就是行指针,
例如图上, 我希望我 p = a
p可以等于a
int (*p)[3] 这个的意思就是声明一个指针, 这个指针+1就是移动三个整数 ,这个类型是指针类型 (行指针)
一级指针加1就是移动一个数
如果把一个指针直接赋值成字符串的话 , 它是让指针存储了字符串常量的起始地址, 也就 意味着你不能通过指针来修改这个代码, 这个指针常量跟static一样会放到一个固定位置,只有程序结束才会回收内存的 ,
但是指针本身是可以动的 比如 p++
指针本身是可以动的, 指向的字符串常量是不能修改和变动的
声明的常量不能改变, 但是指针本身可以移动改变
字符串常量不能更改
一级指针加1就是移动一个数
注意 & 和 =
指针数组一般都可以和二级指针结合, 因为,指针数组里每个数都是一个一级指针
void 指针 和 const
对于void指针 , 在没有强制类型转换之前 , 不能进行任何指针的算术运算 .
因为void指针 ++ – 是没有规律的
如果没有强制类型转换 程序会自动给你进行隐式转换 .
这里的p++ 是void指针类型的++ 只移动一个位置而不是一个类型所占用的字节
使用void 让函数使用范围更广, 使用功能更强大