博客
关于我
C指针 取地址符& 取值符*
阅读量:145 次
发布时间:2019-02-27

本文共 3819 字,大约阅读时间需要 12 分钟。

int 	*MFSS_Pointer;#define    	  FPGA_ADDR	  		0x0a0000000//CE2  MFSS_Pointer = (int*)(FPGA_ADDR+4*i);			*MFSS_Pointer = (data_q<<16)+data_i;

第一行定义一个指针,名字是MFSS_Pointer

第二行宏定义,“#”表示这是一条预处理命令,“define”为宏命令。宏定义只是一个方便替换的操作,代码中遇到FPGA_ADDR直接替换为0x0a0000000。说白了#define 并不是进行变量定义,所以就不需要指定“变量”类型了。它只是一个数-符替换工具罢了。
第三行:(FPGA_ADDR+4i)是一个数,(int)(FPGA_ADDR+4i)强制类型转换,把(FPGA_ADDR+4i)转换成一个指向int型的指针(即一个内存,内存没名字,它指向(FPGA_ADDR+4i)这个地址);MFSS_Pointer = (int)(FPGA_ADDR+4i);把这个内存叫做MFSS_Pointer。这是直观理解。总起来就是,指针MFSS_Pointer指向位置(FPGA_ADDR+4i)
第四行*MFSS_Pointer指向的地方赋值。

1.关于C语言指针中 * 的位置

char* a,b;等价于char *a;char b;而不等价于char *a;char *b;所以写成char *a,b;更不容易引起歧义。

2.取地址运算符和取值运算符

获取某个变量的地址,使用取地址运算符&,如:

char* pa = &a;int* pb = &f;

如果反过来,你要访问指针变量指向的数据,那么你就要使用取值运算符*,如:

printf("%c, %d\n", *pa, *pb);

这里你可能发现,定义指针的时候也使用了,这里属于符号的「重用」,也就是说这种符号在不同的地方就有不同的用意:在定义的时候表示「定义一个指针变量」,在其他的时候则用来「获取指针变量指向的变量的值」。*

直接通过变量名来访问变量的值称之为直接访问,通过指针这样的形式访问称之为间接访问,因此取值运算符有时候也称为「间接运算符」。

比如:

//Example 01//代码来源于网络,非个人原创#include 
int main(void){ char a = 'f'; int f = 123; char* pa = &a; int* pf = &f; printf("a = %c\n", *pa); printf("f = %d\n", *pf); *pa = 'c'; *pf += 1; printf("now, a = %c\n", *pa); printf("now, f = %d\n", *pf); printf("sizeof pa = %d\n", sizeof(pa)); printf("sizeof pf = %d\n", sizeof(pf)); printf("the addr of a is: %p\n", pa); printf("the addr of f is: %p\n", pf); return 0;}

程序实现如下:

//Consequence 01a = ff = 123now, a = cnow, f = 124sizeof pa = 4sizeof pf = 4the addr of a is: 00EFF97Fthe addr of f is: 00EFF970

3.避免访问未初始化的指针

void f(){       int* a;    *a = 10;}

像这样的代码是十分危险的。因为指针a到底指向哪里,我们不知道。就和访问未初始化的普通变量一样,会返回一个「随机值」。但是如果是在指针里面,那么就有可能覆盖到「其他的内存区域」,甚至可能是系统正在使用的「关键区域」,十分危险。不过这种情况,系统一般会驳回程序的运行,此时程序会被「中止」并「报错」。要是万一中奖的话,覆盖到一个合法的地址,那么接下来的赋值就会导致一些有用的数据被「莫名其妙地修改」,这样的bug是十分不好排查的,因此使用指针的时候一定要注意初始化。

4,scanf中取地址符号的使用

int main(void){       int a;    int* p = &a;        printf("请输入一个整数:");    scanf("%d", &a);//此处需要&    printf("a = %d\n", a);        printf("请再输入一个整数:");    scanf("%d", p);//此处不需要&    printf("a = %d\n", a);        return 0;}

程序运行如下:

//Consequence 02请输入一个整数:1a = 1请再输入一个整数:2a = 2
字符串地址
//Example 03#include 
int main(void){ char url[100]; url[99] = '\0'; printf("请输入TechZone的域名:"); scanf("%s", url);//此处也不用& printf("你输入的域名是:%s\n", url); return 0;}

程序执行如下:

//Consequence 03请输入TechZone的域名:www.techzone.ltd你输入的域名是:www.techzone.ltd

数组名其实就是一个「地址信息」,实际上就是数组「第一个元素的地址」

//Example 03 V2#include 
int main(void){ char url[100]; printf("请输入TechZone的域名:"); url[99] = '\0'; scanf("%s", url); printf("你输入的域名是:%s\n", url); printf("url的地址为:%p\n", url); printf("url[0]的地址为:%p\n", &url[0]); if (url == &url[0]) { printf("两者一致!"); } else { printf("两者不一致!"); } return 0;}

程序运行结果为:

//Comsequense 03 V2请输入TechZone的域名:www.techzone.ltd你输入的域名是:www.techzone.ltdurl的地址为:0063F804url[0]的地址为:0063F804两者一致!

%p是打印地址的

5.指向数组的指针

刚刚我们验证了数组的地址就是数组第一个元素的地址。那么指向数组的指针自然也就有两种定义的方法:

...char* p;//方法1p = a;//方法2p = &a[0];

6.指针的运算

当指针指向数组元素的时候,可以对指针变量进行「加减」运算,+n表示指向p指针所指向的元素的「下n个元素」,-n表示指向p指针所指向的元素的「上n个元素」。并不是将地址加1。

如:

//Example 04#include 
int main(void){ int a[] = { 1,2,3,4,5 }; int* p = a; printf("*p = %d, *(p+1) = %d, *(p+2) = %d\n", *p, *(p + 1), *(p + 2)); printf("*p -> %p, *(p+1) -> %p, *(p+2) -> %p\n", p, p + 1, p + 2); return 0;}

执行结果如下:

//Consequence 04*p = 1, *(p+1) = 2, *(p+2) = 3*p -> 00AFF838, *(p+1) -> 00AFF83C, *(p+2) -> 00AFF840

其实使用指针法来访问数组的元素,不一定需要定义一个指向数组的单独的指针变量,因为数组名自身就是指向数组「第一个元素」的指针,因此指针法可以直接作用于数组名:

...printf("p -> %p, p+1 -> %p, p+2 -> %p\n", a, a+1, a+2);printf("a = %d, a+1 = %d, a+2 = %d", *a, *(a+1), *(a+2));...

执行结果如下:

p -> 00AFF838, p+1 -> 00AFF83C, p+2 -> 00AFF840b = 1, b+1 = 2, b+2 = 3

来源:http://www.techzone.ltd/post/CPointer/

转载地址:http://fqlb.baihongyu.com/

你可能感兴趣的文章
MySQL 数据类型和属性
查看>>
mysql 敲错命令 想取消怎么办?
查看>>
Mysql 整形列的字节与存储范围
查看>>
mysql 断电数据损坏,无法启动
查看>>
MySQL 日期时间类型的选择
查看>>
Mysql 时间操作(当天,昨天,7天,30天,半年,全年,季度)
查看>>
MySQL 是如何加锁的?
查看>>
MySQL 是怎样运行的 - InnoDB数据页结构
查看>>
mysql 更新子表_mysql 在update中实现子查询的方式
查看>>
MySQL 有什么优点?
查看>>
mysql 权限整理记录
查看>>
mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
查看>>
MYSQL 查看最大连接数和修改最大连接数
查看>>
MySQL 查看有哪些表
查看>>
mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
查看>>
MySql 查询以逗号分隔的字符串的方法(正则)
查看>>
MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
查看>>
mysql 查询数据库所有表的字段信息
查看>>
【Java基础】什么是面向对象?
查看>>
mysql 查询,正数降序排序,负数升序排序
查看>>