穿越内存迷宫:C语言地址与指针的的冒险之旅

news2025/3/16 6:43:26

前言

C语言的魅力在于其直接的内存控制,而地址和指针是这种控制的核心。深入了解这些概念,将帮助我们更好地理解和利用C语言的潜力。本文将带领你踏上地址与指针的奇妙之旅,揭示它们在程序设计中的神秘面纱。

奇妙指针之旅:解码C语言中地址的秘密

文章目录

  • 前言
  • 奇妙指针之旅:解码C语言中地址的秘密
    • 示例与应用
      • 1. **基本定义和输出**
      • 2. **函数参数传递**
      • 3. **交换函数**
  • 地址和指针
    • 基础知识
      • 1. **变量和内存地址:**
      • 2. **指针的概念:**
      • 3. **使用指针访问数据:**
      • 4. **指针和数组:**
      • 5. **指针运算:**
      • 6. **空指针和野指针:**
      • 7. **指针和函数:**
    • 示例
      • 1. 基本定义和输出
        • 介绍:
      • 2. 函数 `fun_1`:按值传递参数
        • 介绍:
      • 3. 函数 `fun_2`:引用传递参数
        • 介绍:
      • 4. 函数 `fun_3`:指针传递参数
        • 介绍:
      • 5. 交换函数:引用方式
        • 介绍:
      • 6. 交换函数:指针方式
        • 介绍:
      • 7. 函数调用和输出
        • 介绍:
    • 总结

示例与应用

1. 基本定义和输出

演示如何定义变量、引用和指针,并打印它们的初始值和地址。

2. 函数参数传递

通过函数 fun_1fun_2fun_3 展示了按值、引用和指针传递参数的不同方式,以及它们对原始数据的影响。

3. 交换函数

展示了通过引用和指针方式交换两个整数值的函数,突显了引用和指针在函数中的实际运用。

地址和指针

基础知识

当我们谈到C语言中的地址和指针时,我们实际上在讨论如何有效地管理和操作计算机内存。让我们从基础开始:

1. 变量和内存地址:

在C语言中,变量是程序中用于存储数据的标识符。每个变量都有一个关联的内存地址,这是它在计算机内存中的位置。

int num = 42;

在这个例子中,num 是一个整数变量,它存储了值 42,并且在内存中有一个地址,我们可以通过 & 操作符获取这个地址:

printf("变量num的地址是:%p", &num);

2. 指针的概念:

指针是一种特殊类型的变量,它存储的不是值本身,而是一个地址。通过指针,我们可以直接访问和修改内存中的数据。

int *ptr; // 定义一个整数型指针
ptr = # // 将指针指向变量num的地址

在这个例子中,ptr 是一个整数型指针,通过 &num 将它指向了变量 num 的地址。

3. 使用指针访问数据:

一旦我们有了指针,我们可以通过解引用操作符 * 来访问指针所指向的内存中的值。

printf("通过指针访问的值是:%d", *ptr);

这将输出 42,因为指针 ptr 指向了存储 num 的内存地址,通过 *ptr 我们得到了这个地址上的值。

4. 指针和数组:

指针和数组在C语言中密切相关。数组名本质上就是一个指针,它存储了数组第一个元素的地址。

int arr[3] = {10, 20, 30};
int *arrPtr = arr; // 数组名arr就是指向数组第一个元素的指针

printf("第一个元素的值:%d", *arrPtr);

5. 指针运算:

指针可以进行简单的算术运算。例如,通过增加指针的值,我们可以让指针指向下一个元素。

int arr[3] = {10, 20, 30};
int *ptr = arr;

printf("第一个元素:%d\n", *ptr); // 输出第一个元素
ptr++; // 指针移动到下一个元素
printf("移动后的元素:%d", *ptr); // 输出移动后的元素

6. 空指针和野指针:

空指针是指不指向任何有效内存地址的指针。野指针是指指向未知或无效地址的指针。在使用指针之前,务必确保它指向有效的内存。

int *nullPtr = NULL; // 空指针
int *wildPtr; // 野指针,未初始化的指针

7. 指针和函数:

指针也可以作为函数参数,通过引用传递可以修改原始数据。

void increment(int *x) {
    (*x)++;
}

int main() {
    int num = 5;
    increment(&num);
    printf("增加后的值:%d", num);
    return 0;
}

这是一个简单的介绍,C语言中指针的使用非常广泛,它们为程序员提供了更多的控制和灵活性,但也需要小心使用,以避免潜在的错误和内存泄漏。

示例

1. 基本定义和输出

#include <stdio.h>

int main() {
    // 定义整数变量 x,引用 b,指针 p
    int x = 0;
    int &b = x; // 引用 b 是 x 的别名
    int *p = &x; // 指针 p 存储 x 的地址

    // 打印初始值和地址
    printf("Initial Values:\n");
    printf("x: %d\n", x);
    printf("&x: %p\n", (void *)&x);
    printf("b: %d\n", b);
    printf("&b: %p\n", (void *)&b);
    printf("*p: %d\n", *p);
    printf("p: %p\n", (void *)p);

    return 0;
}
介绍:
  • 在这个部分,我们定义了一个整数变量 x,一个引用 b,和一个指向整数的指针 p
  • 引用 bx 的别名,指针 p 存储了 x 的地址。
  • 打印了变量 x、引用 b、指针 p 的值和地址。
    在这里插入图片描述

2. 函数 fun_1:按值传递参数

#include <stdio.h>

// 函数 fun_1 接受整数按值传递,修改不影响调用者
void fun_1(int a) {
    a = 5;
}

int main() {
    int x = 10;

    // 打印调用前的值
    printf("Before fun_1: %d\n", x);

    // 调用 fun_1
    fun_1(x);

    // 打印调用后的值
    printf("After fun_1: %d\n", x);

    return 0;
}
介绍:
  • fun_1 是一个函数,接受整数参数 a
  • 由于参数是按值传递的,对 a 的修改不会影响调用者的变量。
  • 在主函数中,定义了整数变量 x,打印了调用 fun_1 前后的值,以验证 fun_1x 的影响。
    在这里插入图片描述

3. 函数 fun_2:引用传递参数

#include <stdio.h>

// 函数 fun_2 接受整数引用,修改影响调用者
void fun_2(int &a) {
    a = 5;
}

int main() {
    int x = 10;

    // 打印调用前的值
    printf("Before fun_2: %d\n", x);

    // 调用 fun_2
    fun_2(x);

    // 打印调用后的值
    printf("After fun_2: %d\n", x);

    return 0;
}
介绍:
  • fun_2 是一个函数,接受整数引用 a
  • 由于引用是传址的,对 a 的修改会直接影响调用者的变量。
  • 在主函数中,定义了整数变量 x,打印了调用 fun_2 前后的值,以验证 fun_2x 的影响。
    在这里插入图片描述

4. 函数 fun_3:指针传递参数

#include <stdio.h>

// 函数 fun_3 接受整数指针,通过指针修改调用者的值
void fun_3(int *a) {
    *a = 5;
}

int main() {
    int x = 10;

    // 打印调用前的值
    printf("Before fun_3: %d\n", x);

    // 调用 fun_3
    fun_3(&x);

    // 打印调用后的值
    printf("After fun_3: %d\n", x);

    return 0;
}
介绍:
  • fun_3 是一个函数,接受整数指针 a
  • 通过指针修改 *a 的值,实际上是修改了指针指向的地址上的值。
  • 在主函数中,定义了整数变量 x,打印了调用 fun_3 前后的值,以验证 fun_3x 的影响。
    在这里插入图片描述

5. 交换函数:引用方式

#include <stdio.h>

// 通过引用交换两个整数的值
void swapByReference(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 5;
    int y = 10;

    // 打印交换前的值
    printf("Before swapByReference: x=%d, y=%d\n", x, y);

    // 调用交换函数
    swapByReference(x, y);

    // 打印交换后的值
    printf("After swapByReference: x=%d, y=%d\n", x, y);

    return 0;
}
介绍:
  • swapByReference 是一个通过引用交换两个整数值的函数。
  • 使用了一个辅助变量 temp,通过引用直接修改了传入的两个变量的值。
  • 在主函数中,定义了两个整数变量 xy,打印了交换前后的值,以验证 swapByReference 的效果。
    在这里插入图片描述

6. 交换函数:指针方式

#include <stdio.h>

// 通过指针交换两个整数的值
void swapByPointer(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5;
    int y = 10;

    // 打印交换前的值
    printf("Before swapByPointer: x=%d, y=%d\n", x, y);
    // 调用交换函数
    swapByPointer(&x, &y);

    // 打印交换后的值
    printf("After swapByPointer: x=%d, y=%d\n", x, y);

    return 0;
}
介绍:
  • swapByPointer 是一个通过指针交换两个整数值的函数。
  • 使用了一个辅助变量 temp,通过指针直接修改了传入的两个变量的值。
  • 在主函数中,定义了两个整数变量 xy,打印了交换前后的值,以验证 swapByPointer 的效果。
    在这里插入图片描述

7. 函数调用和输出

#include <stdio.h>

int main() {
    int x = 10;
    int &b = x; // 引用 b 是 x 的别名
    int *p = &x; // 指针 p 存储 x 的地址

    // 调用函数和交换函数
    fun_1(x);
    printf("\nAfter fun_1:\n");
    printf("x: %d\n", x);

    fun_2(x);
    printf("\nAfter fun_2:\n");
    printf("x: %d\n", x);

    fun_3(&x);
    printf("\nAfter fun_3:\n");
    printf("x: %d\n", x);

    // 使用引用和指针交换值
    swapByReference(x, b);
    printf("\nAfter swapByReference:\n");
    printf("x: %d\n", x);

    swapByPointer(&x, p);
    printf("\nAfter swapByPointer:\n");
    printf("x: %d\n", x);

    return 0;
}
介绍:
  • 主函数中调用了前面介绍的各个函数和交换函数。
  • 打印了调用函数和交换函数后的变量值。

总结

掌握C语言中的地址与指针是提升编程技能的关键一步。地址与指针不仅仅是内存管理的工具,更是解锁程序性能和灵活性的钥匙。通过学习本文提供的知识,你将能够更自信、更精通地应对C语言编程中的各种挑战。

在这场奇妙的指针之旅中,我们将穿越C语言内存的迷宫,揭示地址与指针的神奇力量。无论你是初学者还是有经验的开发者,本文将为你打开一扇通向C语言深奥世界的大门。准备好迎接挑战,一同探索指针的魔法!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1197151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

好物周刊#30:Github 上大学

https://github.com/cunyu1943/JavaPark https://yuque.com/cunyu1943 村雨遥的好物周刊&#xff0c;记录每周看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;每周五发布。 一、项目 1. Fighting Design 一款灵活、优质的组件库&#xff0c;可在 vue3 应用程…

C语言 音乐播放器项目(综合)

1.main.c文件 #include<stdio.h> #include<stdlib.h> #include<string.h> #include <unistd.h>//休眠所需的头文件 #include "./pos/console.h"//光标使用所需的头文件 #include "lrc.h" #include "./mplayer/start_mplayer…

让你的win10/win11系统变得不再卡顿,优雅草伊凡整理-长期更新-如何让windows操作系统不用老是重装在不断的更新中依然保持流畅运行

概述 如题&#xff1a;让你的win10/win11系统变得不再卡顿&#xff0c;优雅草伊凡整理-长期更新-如何让windows操作系统不用老是重装在不断的更新中依然保持流畅运行 本文长期更新&#xff0c;本次更新2023年11月8日&#xff01; 很多时候 我们的win10win11系统不管再怎么关…

基于SSM的软考系统设计实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

Servlet作业小练习

一.题目 利用JavaBean实现用户类&#xff0c;包含姓名、性别、爱好&#xff0c;爱好需要用多选框 实现表单1进行获取数据&#xff0c;表单2显示获取结果。 利用Servlet实现逻辑代码 二.实现效果 三.具体实现 1.User实体类 package com.hjj.pojo;/*** author:嘉佳 Date:20…

【蓝桥杯软件赛 零基础备赛20周】第3周——填空题

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 文章目录 00. 2023年第14届参赛数据0. 上一周答疑1. 填空…

环境变量小节

这是写的第二篇环境变量博客&#xff0c;写了一年多了&#xff0c;第一次出现把自己博客删了的情况&#xff0c;不知道为什么明明发表了&#xff0c;然后就把草稿箱和回收站的删了&#xff0c;结果晚上发现没发表&#xff0c;回收站删除是无法找回的&#xff0c;以后还是要慎重…

酷柚易汛ERP-账户管理操作指南

1、应用场景 对账户进行管理&#xff0c;可设置账户当前余额、期初余额和设置是否为默认账户。 2、主要操作 2.1 新增支付账户 打开【资料】-【账款管理】&#xff0c;点击【新增】添加账户类别&#xff0c;输入相关信息并保存&#xff0c;账户编号和名称为必录项。&#x…

VirtualBox网络地址转换(NAT),宿主机无法访问虚拟机的问题

问题&#xff1a;NAT模式下&#xff0c;默认只能从内访问外面&#xff0c;而不能从外部访问里面&#xff0c;所以只能单向ping通&#xff0c;虚拟机的ip只是内部ip。 PS&#xff1a;桥接则是与主机公用网卡&#xff0c;有独立的外部ip。 解决&#xff1a;NAT模式可以通过配置 …

最简WebClient 同步、异步调用示例

目录 一&#xff0c;序言二&#xff0c;简单示例1. 引入依赖2. 日志配置3. 调用代码4. 运行结果 三&#xff0c;完整代码 一&#xff0c;序言 WebClient是Spring WebFlux模块提供的一个非阻塞的基于响应式编程的进行Http请求的客户端工具&#xff0c;从Spring5.0开始WebClient…

【JavaEE初阶】 TCP协议详细解析

文章目录 &#x1f332;TCP协议的概念&#x1f6a9;TCP协议段格式&#x1f6a9;TCP的特性 &#x1f333;TCP原理&#x1f6a9;确认应答机制&#xff08;安全机制&#xff09;&#x1f6a9;超时重传机制&#xff08;安全机制&#xff09;&#x1f6a9;三次握手四次挥手&#xff…

【蓝桥杯选拔赛真题65】Scratch水下探险 少儿编程scratch图形化编程 蓝桥杯创意编程选拔赛真题解析

目录 scratch水下探险 一、题目要求 编程实现 二、案例分析 1、角色分析

概念解析 | Richardson-Lucy去卷积算法

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:Richardson-Lucy去模糊算法 Richardson-Lucy去模糊算法:重现图像的真实面目 Blind deconvolution by means of the Richardson–Lucy algorithm 背景介绍 在图像处理中,图像获取…

jQuery实现二级菜单

jQuery怎么实现二级菜单呢&#xff1f;让我为大家演示一个例子&#xff01; 上代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title><style>* {margin: 0;padding: …

Spring源码系列-Spring事务

声明式事务 spring事务&#xff0c;是通过数据库连接来实现的&#xff0c;当前线程中保存了一个map&#xff0c;key是数据原&#xff0c;value是数据库连接 我们说的同一个事务&#xff0c;其实指的是同一个数据库连接&#xff0c;只有拥有同一个数据库连接才能同时提交和回滚。…

C语言实现编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n

完整代码&#xff1a; /*编写一个函数&#xff0c;输入n为偶数时&#xff0c;调用函数求1/21/4...1/n,当输入n为奇数时&#xff0c; 调用函数1/11/3...1/n */ #include<stdio.h>//n为偶数 double Odd(int n){double sum0;//i为2&#xff0c;4&#xff0c;6....for (int …

mybatis的简单教程

整体就是mysql里存了一张表&#xff0c;然后在java程序里用mybatis把数据读出来的一个简单示例。 库 blog里有一张表 article 整个项目就是增加了这3个文件 首先是mybatis-config.xml文件 <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE c…

【Python】20大报告生成词云

这个我其实写过一篇类似的博客&#xff0c;但是那个的文件对象是.csv&#xff0c;对应到.docx文件的话&#xff0c;就不太适用了。如下&#xff1a; Python生成词云-CSDN博客 代码&#xff1a; import jieba import os import wordcloud import numpy as np from PIL import…

多测师肖sir_高级金牌讲师_ui自动化po框架版本01

ui自动化po框架 一、po框架 1、基本介绍 &#xff08;1&#xff09;po模式是page object model的缩写&#xff08;简称&#xff1a;po或pom&#xff09; &#xff08;2&#xff09; po模式的核心思想&#xff1a;分层&#xff0c;实现耦合 实现&#xff1a;业务流程与页面元素操…

n-gram语言模型——文本生成源码

n-gram语言模型——文本生成源码 n-gram模型的基本原理 文本生成的步骤 1. 准备和分词 2. 构建n-gram模型 3. 平滑技术的应用 4. 生成文本 源码 在自然语言处理的领域中&#xff0c;n-gram语言模型是一种基础而强大的工具。它通过考虑词汇的序列来预测文本内容&#xff…