黑马程序员技术交流社区
标题: 【笔记】C语言核心知识点相关总结(二) [打印本页]
作者: 倾心莫若初见 时间: 2017-2-28 14:20
标题: 【笔记】C语言核心知识点相关总结(二)
三、一级指针
1. 指针的使用: 32位系统下是 4 个字节,64位系统下是 8 个字节
1)在定义的时候用 * 号,代表这个变量那个是指针类型
int a = 10; //定义一个整型变量,存储整数 10
int *p = &a; //定义一个整型指针变量,存储a的地址
2)在配合表达式使用 * 号,代表取值运算符,可以取出这个地址里的值
printf("%d\n", *p); // 打印p指向的地址里的值
printf("%d\n",*(&a)); // 打印a这个地址里的值
printf("%d\n", *p + 1); // 取出值,再加1打印出来
2. 指针的几种特殊定义方式:
1) int * const p;
指针常量:p 是 int*类型,那么const修饰的是p,所以p是常量,表示p指向的地址不可修改,
也就是说,p不能再指向别的地方了,但是可以修改p指向的这个地址里的值。
举例:
int a = 10;
int b = 20;
int * const p = &a;
p = &b; //错误
*p = 100; //允许
2) const int *p;
int const *p;
常量指针:p 是 int*类型,那么const修饰的是*p,所以*p是常量,表示p指向的地址里的值不可修改,
也就是说,p里的值不能再重新赋值了,但是可以修改p指向的地址。
int a = 10;
int b = 20;
const int *p = &a;
p = &b; //可以
*p = 100; //错误
3) const int * const p;
常量指针常量:p 是 int*类型,那么const分别修饰了p 和 *p,所以p和*p都是常量,表示p指向的地址不可修改,
同时p指向的地址里的值也不可修改。
int a = 10;
int b = 20;
const int *const p = &a;
p = &b; //错误
*p = 100; //错误
《C Primer Plus》 : "自由的代价,是永远的警惕。"
你定义了一个指针,那就一定要知道这个指针指向的什么地方,而且你要保证这个指针是真实有效的,否则我就用程序崩溃来惩罚你。
四、多级指针
#include <stdio.h>
int main(void)
{
int a = 10;
int *p = &a; //定义一个一级指针变量,存储了整型变量a的地址
int **pp = &p; //定义一个二级指针变量,存储了整型一级指针变量p的地址
int ***ppp = &pp; //定义了一个三级指针变量,存储了整型二级指针变量pp的地址
printf("%p, %p, %p, %p\n", &a, &p,&pp, &ppp);
// 分别打印各个变量自身所在的内存地址
printf("%p, %p, %p, %p\n", &a, p, pp, ppp);
//printf("%d", a); 用%d的形式打印a的值:整数
//printf("%p", p); 用%p的形式打印p的值:地址
// &a : 打印 变量 a 的地址
// p:打印变量 a的地址
// pp: 打印变量 p 的地址
// PPP:打印变量 pp 的地址
printf("%p, %p, %p, %p\n", &a, p, *pp,**ppp);
// &a : 打印 变量 a 的地址
// p:打印变量 a 的地址
// *pp:打印变量 a 的地址
//**PPP: 打印变量 a 的地址
printf("%d, %d, %d, %d\n", a, *p, **pp, ***ppp);
// a: 打印 10
// *P: 打印 10
// **pp:打印 10
// ***ppp: 打印 10
}
五、指针 和 数组的用法
int num[5] = {10, 20, 30, 40, 50};
int *p = num;
打印的值 打印后*p的值是 数组里的原值
// 操作地址
*p++ 10 20 10
*(p++)
*和++的优先级相同,根据结合性(从右往左),那么p先和后自增运算符++结合,
++操作将在表达式完成后进行自增,也就取出p指向的值之后,p指向的下标后移一位(4个字节)。
*++p 20 20 10
*(++p)
*和++优先级相同,根据结合性(从右往左),那么p先和前自增运算符++结合,
++操作将会立即完成,p指向的下标后移一位(4个字节),然后再取出p指向的值。
// 操作数值
(*p)++ 10 11 11
根据优先级()小括号优先级最高,p先和*相结合,然后再和后自增运算符++结合,
因为是后自增,所以先打印当前下标的值,然后在原值的基础上自增 1,此时原值已被改变
++*p 11 11 11
++(*p)
根据结合性/优先级,*和p先结合,然后再和前自增运算符++结合,
因为是前自增,所以先在原值的基础上自增1,然后在打印这个值,此时原值已被改变。
总结:如果一个表达式里有多个运算符,则先进行优先级比较,先执行优先级高的运算符;
如果优先级相同,那就看结合性,根据结合方向来做运算。
结合性:
从左往右:
小括号()、数组括号[]、成员选择 . 和 ->,双目运算符,逗号运算符
从右往左:
单目运算符、三目运算符、赋值类运算符
/*
++a: 是直接从变量 a 所在的内存地址中取值,并进行加1操作,再执行表达式剩余部分。
a++: 先把变量的值保存在一个临时寄存器里,然后再执行整个表达式,执行完之后,再把a的值自增1,再返回内存里。
CPU -》 寄存器 -》 缓存(L1\L2\L3) -》来自于内存
CPU只和寄存器做数据交换,对于重复操作的数据会放在缓存里。
但是不管寄存器还是缓存,他们的数据都来自于内存。
*/
未完待续,请看下一篇《C语言核心知识点相关总结(三)》
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |