您现在的位置是:首页 > 正文

在c语言中 对地址的操作的作用,C语言中地址操作符&的使用

2024-02-29 12:55:18阅读 1

示例一

#include

int find(int *a);

main()

{

int b = 1;

int wait, test;

test = find(&b);

printf("内存地址为:%d",&test);

scanf("%d", &wait);

}

int find(int *a)

{

return *a;

}

int b = 1; int test = find(&b); 这样调用时,实际上是进行了:int* a = &b,创建了一个新的指向b的整型指针a作为find函数范围内的局部变量。

示例二

函数声明:int find(int& a); 函数调用:int b = 1; int n = find(b);

这样调用时,实际上是进行了:int& a = b,给变量b起了个别名a,也就是说a和b实际上代表的是同一个变量,调用期间没有创建任何新的变量。

示例三

函数声明:int find(int a); 函数调用:int b = 1; int n = find(b);

这样调用时,实际上是进行了:int a = b,也就是普通的变量赋值操作,调用期间创建了在find函数范围内的局部变量a,它的值与b相同。

C中*、&用法介绍

&在用于计算时就是取变量地址,如int* a = &b,就是将整型变量b的地址取出,赋值给整型指针a,a中的内容就是b的地址,所以a指向b。

*在用于计算时,就是取指针所指向的地址中的值,如int b = *a,就是将整型指针a指向的地址中存放的内容赋值给整型变量b。

C语言中,&符号大家一定很熟悉吧,它除了可以作为按位运算“与”之外还有更常用的功能——取变量地址。

#include

main()

{

int a = 0;

int wait;

int *p = &a;

printf("The value is: %d\n", *p);

scanf("%d", &wait);

}

上面代码中,指针p指向变量a的地址。在C/C++中,每个变量都有其相应的地址,通过在变量标识符前加&符号即可获得变量的地址。

那么我们这么写可以吗?int *p = &0x01000;

这显然不行。因为对于一个数值常量,它是没有地址的。而变量之所以有地址就是因为要有一个存储单元对变量进行标识(当然,变量也可以直接映射到某个寄存器)。

我们再看下面的代码:

#include "stdio.h"

int main(void)

{

int a = 0; // &a = 0x0012ff60

int *p = &*(int*)0x0012ff60;

printf("The value is: %d\n", *p);

return 0;

}

上面代码又是怎么回事呢?

先前已经调查过变量a的地址——0x0012ff60,那么这里的指针p实际上也是指向变量a的地址。

首先,将0x0012ff60作为int*,这时它与&a是等价的。

然后*(int*)0x0012ff60表示取变量a的内容。

最后,&*(int*)0x0012ff60表示再脱去*(int*)0x0012ff60的解引用,相当于又变为(int*)&a。

因此,这里的&与第一个例子中的&是不同的语义。这里的&不是取地址,因为一个*(int*)0x0012ff60不是变量,它是没有地址的。每一个变量标识符在编译期间,编译器会为它们创建一个符号表,其中存放着变量标识符相应的各种属性,如类型、地址标识等。地址标识在连接后即可确定逻辑地址值。简而言之,&作为取地址操作,当且仅当&后面跟着的是变量或函数标识符。所以这里的&表示脱去解引用。

由此我们可以得出:&作为取地址操作时,其行为结果是在编译时就被确定的;而*,解引用操作(或取内容)操作,其行为结果只能在运行时才可被确定。

再看下面的例子,加深印象:

#include "stdio.h"

int main(void)

{

int a = 0;

int *p = &*&*&a;

printf("The value is: %d\n", *p);

return 0;

}

在C++中,&还可以表示引用,这个就不多说了。

#include "iostream"

using namespace std;

int main(void)

{

int a = 0;

int &r = a;

cout << "The value is: " << r << endl;

return 0;

}

网站文章

  • tlv编码

    解码

    2024-02-29 12:54:50
  • 2.2.2 顺序表的删除操作

    2.2.2 顺序表的删除操作

    ListDelete(SqList &L,int i,int &e)删除顺序表L第i个元素。①&e,引用型变量,保证定义的ListDelete()方法中的e会带回给main函数。--int &e表示把此次删除的数据返回。

    2024-02-29 12:54:44
  • Python爬虫这么简单却还是学不会?13天教你学会Python爬虫分布式

    Python爬虫这么简单却还是学不会?13天教你学会Python爬虫分布式

    1.爬虫是什么 网络爬虫(web crawler 简称爬虫)就是按照一定规则从互联网上抓取信息的程序,既然是程序那和正常用户访问页面有何区别?爬虫与用户正常访问信息的区别就在于:用户是缓慢、少量的获取...

    2024-02-29 12:54:36
  • RedisTemplate注入以后发现是null报错的解决办法---SpringCloud工作笔记174

    RedisTemplate注入以后发现是null报错的解决办法---SpringCloud工作笔记174

    今天在项目中发现,RedisTemplate怎么也注入不了,执行到使用redistemplate的地方,就显示为null报错,这里说一下怎么解决1.在自己的Redi工具类中:添加一个静态的RedisT...

    2024-02-29 12:54:29
  • RabbitMq延迟队列

    延时队列,延时队列内部是有序的,最重要的特性就体现在它的延时属性上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说,延时队列就是用来存放需要在指定时间被处理的元素的队列死信队列其实也是延迟队列,因为正常队列中设置时间就会发送到死信队列中(消息过期)...

    2024-02-29 12:54:02
  • 程序员该有的艺术气质—SOLID原则

    程序员该有的艺术气质—SOLID原则

    昨天Amazon在我们学校有场讲座,主要是跟我们分享一些经验:作为一个程序员该有的编码硬技术和工作软技术。当然他们也有来我们学校招聘人才的目的,想要吸引我们去他们公司,于我而言,这么牛逼的一个公司我当然特别想去啦,这场讲座我是必听无疑,的确学到了一些知识。没有过实际项目的在校生往往不能写出漂亮的代码(包括编码规范、注释、设计模式、性能等等),因为他们更多注重的正确性,只要结果出来了且是...

    2024-02-29 12:53:55
  • c/c++ 线程进程

    c++进程线程的基础使用

    2024-02-29 12:53:49
  • 微信小程序开发之获取用户头像昵称

    微信小程序开发之获取用户头像昵称

    微信小程序开发之获取用户头像昵称

    2024-02-29 12:53:20
  • 重定义默认参数&&表达式必须包含类类型:解决方案

    重定义默认参数&&表达式必须包含类类型:解决方案

    重定义默认参数&&表达式必须包含类类型:解决方案关于重定义默认参数一般出现在类的重载上(即对相同函数名,但是参数列表不同)。问题代码如下:Myclass.h文件class MyClass{public...

    2024-02-29 12:53:13
  • 洛谷P1443 马的遍历——标准广度优先搜索

    洛谷P1443 马的遍历——标准广度优先搜索

    Solution: 这是一道标准的广度优先搜索题目。我们知道,马在棋盘上是按“日”行走的,也就是有八个方向,我们沿着这八个方向广度优先搜索就可以了。 代码如下: #include #include #include #define MAX 500 using namespace std; int mp[MA...

    2024-02-29 12:53:07