当前位置: 首页 > article >正文

【C语言】一文讲通 和*

&和*详解

      • 前言
      • 符号 `&`:取地址符
        • `&` 的用法
        • `&` 用于函数参数传递
      • 符号 `*`:解引用符
        • `*` 的用法
        • `*` 用于指针的初始化
      • 结合使用 `&` 和 `*`
        • 1. `*` 和 `&` 配合使用示例
      • 常见错误与注意事项
      • 总结

前言

在 C 语言中,*& 是两个非常重要的符号,它们在指针、内存管理和函数参数传递等方面起着关键作用。对于许多初学者来说,理解这两个符号的含义和用法可能会有一定的难度,但只要理清它们的关系和用途,就能够轻松掌握这部分知识。本文将详细讲解 *& 的作用、使用场景,并通过实例帮助大家理解。

符号 &:取地址符

在 C 语言中,& 是“取地址符”。它的作用是获取变量在内存中的地址,即返回变量的指针。

& 的用法

& 用来获取一个变量的内存地址。例如:
在这里插入图片描述

#include <stdio.h>

int main() {
    int num = 10;
    printf("num的内容是: %d\n",  num);
    printf("num的地址是: %p\n", &num);
    return 0;
}

输出:

num的内容是: 10
num的地址是: 0x7ffeeaef7bfc

在这个例子中,&num 获取了变量 num 的内存地址,并将其打印出来。& 运算符返回的是一个指向 num 变量的指针。

& 用于函数参数传递

& 还可以用在函数的参数传递中,表示将变量的地址传递给函数,从而实现按地址传递参数,也就是我们常说的“传引用”。这与按值传递不同,按值传递是将变量的值直接传递给函数。

#include <stdio.h>

void modify(int *ptr) {
    *ptr = 20;  // 修改指针所指向的内存值
}

int main() {
    int num = 10;
    printf("修改前: %d\n", num);
    modify(&num);  // 传递num的地址
    printf("修改后: %d\n", num);
    return 0;
}

输出:

修改前: 10
修改后: 20

main 函数中,我们传递了变量 num 的地址 &num 给函数 modify。在 modify 函数中,通过指针修改了 num 的值。这就是“按地址传递”的体现,允许函数直接修改原始变量的值。

在这个示例中还有一个非常重要的点就是这个函数,因为下文会讲*,所以我们把这个东西留到最后面讲。

void modify(int *ptr) {
    *ptr = 20;  // 修改指针所指向的内存值
}

符号 *:解引用符

在 C 语言中,* 是“解引用符”,它用于指针变量。当我们使用指针时,* 可以用来访问指针指向的内存地址中的值。

定义:数据类型 *指针变量名
含义:
	*指针变量名--代表所指变量的值
	 指针变量名--代表所指变量的地址
* 的用法

* 运算符用于指针变量时,表示解引用,即通过指针访问或修改指针所指向的变量的值。

定义指针变量之后,必须将其与某个变量的地址关联才能使用,关联方式有两种:

  1. 定义时赋初值,定义指针变量时直接指向变量地址。
    例如:

    int a ;
    int *p = &a;
    
  2. 赋值,将普通变量的地址赋值给指针变量。

    int a,*p;
    p=&a;
    

示例代码:

#include <stdio.h>

int main() {
    int num = 10,*p;
    int *ptr = &num;  // ptr 指向 num 的地址
    
    p=&num;// p 指向 num 的地址
    
    printf("num 的值是: %d\n", *ptr);  // 通过 ptr 获取 num 的值
    printf("num 的值是: %d\n", *p);    // 通过 p   获取 num 的值
    return 0;
}

输出:

num 的值是: 10
num 的值是: 10

在这个例子中,ptr 是一个指向 num 的指针,而 *ptr 表示解引用指针,获取指针 ptr 所指向内存地址中的值,即 num 的值。

* 用于指针的初始化

指针变量通常在声明时需要初始化为某个地址值,这个地址可以通过 & 运算符获取。* 运算符通常用来声明指针变量时表示该变量存储的是一个地址,并指向某种数据类型。

#include <stdio.h>

int main() {
    int num = 100;
    int *ptr = &num;  // ptr 是一个指向 int 类型的指针
    printf("num 的地址: %p\n", ptr);
    printf("num 的值: %d\n", *ptr);
    return 0;
}

输出:

num 的地址: 0x7ffeeaef7bfc
num 的值: 100

在此代码中,ptr 是指向 int 类型的指针,指向 num 的地址。通过 *ptr 解引用,我们获得了 num 的值。

结合使用 &*

&* 是互相配合的,它们常常一起使用。我们可以通过 & 获取一个变量的地址,再通过 * 解引用指针访问地址处的值,或者反过来,通过 * 创建一个指针,再用 & 获取指针指向的地址。

1. *& 配合使用示例
#include <stdio.h>

void add_1(int a,int b){
	a = 10;
	b = a + b;
}

void add_2(int *a,int *b){
	*a = 10;
	*b = *a + *b;
}

int main() {
    int a = 5 , b = 3;
    int num_1 , num_2;
	    
	add_1(  a ,  b );
	printf("a = %d , b = %d\n",a,b);  // 打印 a b 的值
	
	add_2( &a , &b );
    printf("a = %d , b = %d\n",a,b);  // 打印 a b 的值
    
    return 0;
}

输出:

a = 5 , b = 3
a = 10, b = 13

在这个例子中,add_1读取了a b 两个变量的值,不能对a,b两个变量本身的值进行改变;add_2使用*解引用,直接对a b两个变量进行操作,既可以读变量的值,也可以修改变量的值。但需要注意的是,使用了*要用&进行地址的赋值。

常见错误与注意事项

  1. 指针未初始化
    使用 * 时,指针必须指向有效的内存地址。如果指针没有初始化,解引用会导致程序崩溃。

    int *ptr;  // 未初始化指针
    *ptr = 10; // 错误:未初始化的指针解引用
    
  2. 误用 &*
    &* 要注意区分使用。& 获取的是地址,而 * 获取的是指针指向的值。如果弄反了,会引发错误。

    int num = 5;
    int *ptr = &num;
    printf("%d\n", &ptr);  // 错误:&ptr 会返回 ptr 的地址,而不是 ptr 指向的值
    

总结

  • & 是取地址符,获取一个变量在内存中的地址。
  • * 是解引用符,用于访问指针指向的内存中的值。
  • 它们通常配合使用,& 用来获取变量的地址,* 用来通过指针访问地址处的值。
  • 使用 *& 时,需要确保指针指向有效的内存地址,否则会出现运行时错误。
    在这里插入图片描述

通过理解并掌握 &* 的用法,你可以深入理解 C 语言中的指针,进而更好地管理内存、实现函数参数的高效传递等操作。


http://www.kler.cn/a/444938.html

相关文章:

  • 怿星科技联合赛力斯举办workshop活动,进一步推动双方合作
  • 基于Arduino的平衡车机械臂
  • 手机便签哪个好用?手机桌面便签app下载推荐
  • SQL进阶技巧:如何根据工业制程参数计算良品率?
  • CVE-2024-32709 WordPress —— Recall 插件存在 SQL 注入漏洞
  • Linux 中 epoll 的详解
  • github快速查找已被删除的文件指令日志
  • Android定时任务实现每隔一段时间切分录音文件,audiorecord实现录音
  • Java全栈项目 - 学生档案管理系统
  • 网络安全等级保护—定级
  • 我在广州学 Mysql 系列——有关 Mysql 函数的练习
  • 发送webhook到飞书机器人
  • Kingbase数据库备份还原操作手册
  • 解锁 Jenkins+Ant+Jmeter 自动化框架搭建新思路
  • 【Ubuntu】设置静态Ip
  • HTML5+CSS3+JS制作精美的宠物主题网站(内附源码,含5个页面)
  • 前端之CSS光速入门
  • 在Win11系统上安装Android Studio
  • 【C#】方法参数的修饰符ref 与 out
  • 华纳云:虚拟服务器之间如何分布式运行?
  • PostgreSQL的交互式终端使用一系列命令来获取有关文本搜索配置对象的信息
  • WPF Binding 绑定
  • linux常用命令(touch、cat、less、head、tail)
  • Scala的惰性求值:深入理解与实践
  • 回归预测模型 | LSTM、CNN、Transformer、TCN、串行、并行模型集合
  • 最大子数组和 最大子数组和(有长度限制) 最大m段子数组和