C指针 取地址符& 取值符*

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 <stdio.h>
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 01
a = f
f = 123
now, a = c
now, f = 124
sizeof pa = 4
sizeof pf = 4
the addr of a is: 00EFF97F
the 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
请输入一个整数:1
a = 1
请再输入一个整数:2
a = 2
字符串地址
//Example 03
#include <stdio.h>
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 <stdio.h>
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.ltd
url的地址为:0063F804
url[0]的地址为:0063F804
两者一致!

%p是打印地址的

5.指向数组的指针

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

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

6.指针的运算

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

如:

//Example 04
#include <stdio.h>
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 -> 00AFF840
b = 1, b+1 = 2, b+2 = 3

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

  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 指针*可以连用是因为它表示解引用操作,即获指针所指向的变量的值。例如,如果有一个int类型的指针p,那么*p就是p所指向的int类型变量的值。因此,可以使用连续的指针*来获多级指针所指向的变量的值。 地址号&不能连用是因为它表示获变量的地址。一个变量只有一个地址,因此不能使用连续的地址号&来获变量的地址。例如,如果有一个int类型的变量a,那么&a就是a的地址,不能使用&&a来获a的地址。 ### 回答2: 指针*连用的原因是为了表示所指向的值。在C语言中,指针是一个特殊类型的变量,它不存储实际的值,而是存储一个内存地址,指向内存中的某个位置。 当我们需要访问指针所指向的值时,可以使用取值操作*。取值操作*可以将指针所指向的地址的内容提出来,返回一个与指针所指向的值类型相匹配的值。这样,我们就可以通过指针来访问和修改实际存储在该内存地址处的值。 而地址号&用于获变量的内存地址。当我们需要获一个变量的地址时,可以使用地址号&加上变量名称,得到该变量所在内存地址。 这两个操作的连用,可以满足我们对于指针的基本需求。我们可以定义一个指针变量,然后通过地址号&获另一个变量的地址,然后将这个地址赋值给指针变量。接着,使用取值操作*可以获地址所对应的值。 总之,指针*可以连用是为了方便我们通过指针来访问、修改内存中存储的值,地址号&则是用于获变量的内存地址。这两个操作的连用可以满足我们对指针的基本需求,提供了灵活而强大的编程能力。 ### 回答3: 指针是C语言中的一种特殊数据类型,它用于存储和处理变量的内存地址指针由两部分组成,即指针变量和所指向的内存地址。 首先,让我们来了解指针变量的作用。指针变量用于存储内存地址,通过它可以访问和操作这些内存地址所对应的数据。为了声明一个指针变量,我们需要使用一个指针类型的关键字(例如int、char等)以及一个星号*。这个星号告诉编译器我们要声明一个指针。 在C语言中,我们可以使用一个星号*来进行取值操作,也就是通过指针变量来获指针所指向的内存地址对应的值。这个星号告诉编译器我们要对指针进行解引用。 另外,我们还可以使用一个地址号&来获一个变量的内存地址。这个&号告诉编译器我们要获变量的地址。 那么为什么指针*可以连用,地址号&呢? 首先,指针变量的声明需要使用一个星号*,这是C语言的语法规定。 其次,指针的解引用操作通过一个星号*来实现,这个星号告诉编译器我们要获指针所指向的内存地址对应的值。 最后,地址号&用于获一个变量的内存地址,这样我们就可以通过指针变量来访问和操作这个变量。 因此,指针*和地址号&是C语言中的两个重要标识,它们的使用是为了能够有效地管理和操作内存地址,实现灵活的数据处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值