C语言复习概要(六)

在这里插入图片描述

公主请阅

    • 1. 深入理解数组与指针在C语言中的应用
      • 1.1 数组名的理解
    • 2. 使用指针访问数组
    • 3. 一维数组传参的本质
    • 4. 冒泡排序的实现
    • 5. 二级指针
    • 6. 指针数组
    • 7. 指针数组模拟二维数组
    • 8.总结

1. 深入理解数组与指针在C语言中的应用

数组与指针是C语言的核心概念之一,理解它们的本质及其相互关系是成为C语言高手的必经之路。数组为我们提供了一种存储大量相同类型数据的高效方式,而指针则为操作这些数据提供了极大的灵活性。本文将从数组名与指针的基本理解出发,深入探讨指针与数组的结合使用,并通过经典的冒泡排序算法和多级指针操作举例说明。

1.1 数组名的理解

数组是存储相同类型数据的线性结构。一个简单的一维数组的声明如下:

int arr[5] = {1, 2, 3, 4, 5};

在这个例子中,arr是一个包含5个int类型元素的数组。但是在更底层的C语言内存模型中,数组名实际上是一个常量指针,它指向数组的第一个元素的地址。也就是说,arr的值是&arr[0]。但需要注意的是,数组名本身是一个常量,不能像普通指针一样被重新赋值。

例如,下面的代码将会报错:

arr = &x; // 错误:数组名是常量,不能被赋值

这一点解释了为什么我们可以通过指针的方式来访问数组的元素:

int *p = arr;

在这个例子中,p指向arr[0],也就是数组的第一个元素。通过指针p,我们可以轻松访问整个数组元素:

for (int i = 0; i < 5; i++) {
    printf("%d ", *(p + i));  // 输出:1 2 3 4 5
}

这说明数组名其实是一种特殊的指针,它和指针的行为非常相似,但在某些情况下,数组名与普通指针的行为略有不同。

2. 使用指针访问数组

使用指针访问数组是C语言中非常常见的操作,它可以提高程序的效率。我们可以通过指针遍历数组,而不是通过索引。

假设有一个数组:

int arr[5] = {10, 20, 30, 40, 50};

你可以通过指针访问数组的每一个元素:

int *ptr = arr;

for (int i = 0; i < 5; i++) {
    printf("Element %d: %d\n", i, *(ptr + i));
}

这里,ptr + i表示指向数组中第i个元素的指针,而*(ptr + i)则解引用该指针,得到对应的值。通过指针直接访问数组元素,避免了使用数组下标的额外计算,从而提升了访问速度。

3. 一维数组传参的本质

在C语言中,函数传递数组参数实际上是传递指针。让我们来看看一个示例:

void printArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
}

在这里,arr实际上是一个指向数组的指针,而不是整个数组。当我们调用这个函数时,传递的实际上是数组的地址:

int arr[5] = {1, 2, 3, 4, 5};
printArray(arr, 5);

这种方式使得数组传参非常高效,因为只需传递数组的首地址即可,而不是整个数组的内容。这样可以节省大量的内存和时间,特别是在处理大型数组时。

4. 冒泡排序的实现

冒泡排序是一种经典的排序算法,借助数组和指针的结合,我们可以用更灵活的方式实现它。让我们看看如何用指针来实现冒泡排序:

void bubbleSort(int *arr, int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (*(arr + j) > *(arr + j + 1)) {
                // 交换两个元素
                int temp = *(arr + j);
                *(arr + j) = *(arr + j + 1);
                *(arr + j + 1) = temp;
            }
        }
    }
}

在这个例子中,我们通过指针访问数组中的元素并进行交换。与直接使用数组下标相比,使用指针能更加灵活地操作内存地址。

5. 二级指针

二级指针(即指向指针的指针)是C语言中的另一个重要概念。它常用于动态分配二维数组或在函数中修改指针的值。假设我们需要通过函数来修改一个指针的指向:

void modifyPointer(int **p) {
    static int x = 10;
    *p = &x;
}

在这个例子中,p是一个二级指针,它指向一个指针。通过解引用p,我们可以改变一级指针的值。在函数调用中:

int *ptr = NULL;
modifyPointer(&ptr);
printf("%d\n", *ptr);  // 输出:10

这展示了如何通过二级指针在函数中修改一级指针的值。

6. 指针数组

指针数组是一个存储指针的数组。它通常用于存储一组字符串或指向其他数组的指针。让我们看看一个指针数组的例子:

char *names[] = {"Alice", "Bob", "Charlie", "David"};

for (int i = 0; i < 4; i++) {
    printf("%s\n", names[i]);
}

在这个例子中,names是一个指针数组,每个元素都是一个指向字符串的指针。通过遍历指针数组,我们可以输出每个字符串。

指针数组在处理动态内存分配和多维数组时非常有用。

7. 指针数组模拟二维数组

二维数组是一种常见的数据结构,但有时候我们需要使用指针数组来模拟二维数组,以获得更大的灵活性。例如,以下代码演示了如何使用指针数组来动态创建一个二维数组:

int rows = 3, cols = 4;
int **arr = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
    arr[i] = (int *)malloc(cols * sizeof(int));
}

// 为数组赋值
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        arr[i][j] = i * cols + j;
    }
}

// 打印数组
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        printf("%d ", arr[i][j]);
    }
    printf("\n");
}

// 释放内存
for (int i = 0; i < rows; i++) {
    free(arr[i]);
}
free(arr);

这里,我们首先分配了一个存储行指针的数组,然后为每一行分配内存。这种方法使得我们可以根据需要动态调整二维数组的大小。

8.总结

数组与指针是C语言中的基础概念,但它们的结合使用可以极大提高程序的灵活性和效率。通过理解数组名的本质、指针访问数组、函数传参中的指针使用、以及指针数组与多级指针的应用,我们可以编写出高效且灵活的C程序。冒泡排序和二维数组的指针模拟为我们展示了指针在实际算法和数据结构中的应用。掌握这些技巧和概念,将帮助你在C语言编程中走得更远。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【安装JDK和Android SDK】

安装JDK和Android SDK 1 前言2 下载2.1 下载途径2.2 JDK下载和安装2.2.1 下载2.2.2 安装并配置环境变量2.2.3 验证 2.3 SDK下载和安装2.3.1 下载2.3.2 安装2.3.3 环境变量配置2.3.4 验证 1 前言 在软件开发中&#xff0c;Android应用开发通常使用Android Studio&#xff0c;但…

使用Milvus和Llama-agents构建更强大的Agent系统

代理&#xff08;Agent&#xff09;系统能够帮助开发人员创建智能的自主系统&#xff0c;因此变得越来越流行。大语言模型&#xff08;LLM&#xff09;能够遵循各种指令&#xff0c;是管理 Agent 的理想选择&#xff0c;在许多场景中帮助我们尽可能减少人工干预、处理更多复杂任…

typescript使用webpack打包编译问题

解决方案&#xff1a;在webpack.config.js中的mdule.exports中设置mode。 再次运行npm run start即可。

【软考】设计模式之中介者模式

目录 1. 说明2. 应用场景3. 结构图4. 构成5. 适用性6. 优点 1. 说明 1.用一个中介对象来封装一系列的对象交互。2.中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。3.中介者模式&#xff08;Mediator Pattern&…

Copilot Coaching新功能铸就Word更强

Copilot 的意思是副驾驶。 现在&#xff0c;您的副驾驶教练来了&#xff1a;Copilot Coaching Copilot Coaching 是 Word 中的一项新 Copilot 功能&#xff0c;可在您查看内容时为您提供支持&#xff0c;以实现语法和拼写之外的改进 - 帮助您澄清想法&#xff0c;并为您提供有…

【优选算法】(第四十篇)

目录 岛屿数量&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 岛屿的最⼤⾯积&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 岛屿数量&#xff08;medium&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;LeetCo…

植物大战僵尸杂交版

最新版植物大战僵尸杂交版 最近本款游戏火爆 下载资源如下&#xff1a; win版本&#xff1a;2.3.7 链接&#xff1a;下载地址 提取码&#xff1a;9N3P Mac&#xff08;苹果版本&#xff09;&#xff1a;2.0.0 链接&#xff1a;下载地址 提取码&#xff1a;Bjaa 介绍&#xff…

【论文#码率控制】ADAPTIVE RATE CONTROL FOR H.264

目录 摘要1.前言2.基本知识2.1 蛋鸡悖论2.2 基本单元的定义2.3 线性MAD预测模型 3.GOP级码率控制3.1 总比特数3.2 初始化量化参数 4.帧级码率控制4.1 非存储图像的量化参数4.2 存储图像的目标比特 5.基本单元级码率控制6.实验结果7.结论 《ADAPTIVE RATE CONTROL FOR H.264》 A…

考研编程:10.11 回文数 水仙花 生成一定范围内的随机数 求二叉树宽度

回文数 #include <stdio.h>int main(){int a,b,c0,sum;scanf("%d",&a);ba;while(b!0){c b%10 c*10;b b/10;}if(ca){printf("yes");}return 0; } 水仙花 #include <stdio.h> #include <math.h> int main(){int a,b,c0,sum;scan…

网络协议原理

文章目录 TCP通信原理TCP与UDP的对比应用层应用层协议 --- tcp协议定制直接传递对象自定义协议现在要解决的问题业务处理 json的使用使用json进行序列化和反序列化操作 总结 TCP通信原理 tcp是面向字节流的 同时他也是面向连接的 所以TCP的服务器编写代码如图所示: 客户端的编…

C语言:在Visual Studio中使用C语言scanf输入%s出现的栈溢出问题

学了C之后就很少使用C语言了&#xff0c;今天帮同学解答C语言问题&#xff0c;遇到了一个我以前没有遇到过的问题。 一、问题描述 先看以下代码&#xff1a; #include<stdio.h> int main() {char str[100] { 0 };scanf_s("%s", str);printf("%s",…

探索极简计算的新边界:从Uxn虚拟机看未来编程生态

越来越多的开发者追求复杂度和功能性的极致,然而,有一个小众的编程社区选择了截然不同的道路——极简主义。Uxn虚拟机便是这一思潮的代表之一。它通过简洁的指令集和有限的硬件资源模拟,试图打造一种可以在多种设备上运行的便携性编程环境。 与主流的重型操作系统和复杂…

Redis面试题——第四篇

1. Redis主从复制的常见拓扑结构有哪些 一主多从&#xff1a;这是最基本的拓扑结构&#xff0c;包含一个主节点和多个从节点&#xff0c;所有写操作都在主节点上执行&#xff0c;而读操作可以在从节点上进行&#xff0c;以提高读取速度和负载均衡。 树状主从结构&#xff1a;从…

模拟电路设计期末速成总结

模拟电路设计期末速成总结 模拟电路设计是电子工程和电气工程专业中的一门重要基础课&#xff0c;主要研究连续时间信号&#xff08;模拟信号&#xff09;的处理和应用。期末复习时&#xff0c;针对这门课可以分为以下几个关键内容进行速成总结。 一、基本概念与元件 模拟信号…

C++设计模式——代理模式

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 引言代理模式的定义代理模式的具体实现 引言 我们经常听到代理服务器「代理服务器是一个中间服务器&#xff0c;能够接收客户端的请求&#xff0c;并代表客户端向服务器发起请求&#xff0c;然后将服…

经典文献阅读之--RGBD GS-ICP SLAM(结合ICP和3D GS构建最快的稠密SLAM)

0. 简介 同时定位与地图构建&#xff08;SLAM&#xff09;的密集表示在机器人技术、虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09;应用中扮演了关键角色。在密集表示SLAM的最新进展中&#xff0c;利用神经场景表示和3D高斯表示以实现高保真的空间表…

Mycat引领MySQL分布式部署新纪元:性能与扩展性的双重飞跃

作者简介&#xff1a;我是团团儿&#xff0c;是一名专注于云计算领域的专业创作者&#xff0c;感谢大家的关注 座右铭&#xff1a; 云端筑梦&#xff0c;数据为翼&#xff0c;探索无限可能&#xff0c;引领云计算新纪元 个人主页&#xff1a;团儿.-CSDN博客 目录 前言&#…

使用OneAPI+Ollama+Dify搭建一个兼容OpenAI的API发布及AI应用开发系统(三)Dify的安装及配置

在GitHub中的AI工作流短代码平台中&#xff0c;Dify获星一直名列前茅&#xff0c;目前已达48K星&#xff0c;其工作稳定性也是非常的高&#xff0c;在这里我们介绍一下Dify的安装。 由于Dify的结构非常的复杂&#xff0c;我们这里介绍Docker的方式进行安装&#xff0c;硬件的最…

Nvidia Jetson Orin平台部署CenterPoint模型

最近尝试将CenterPoint模型部署到Orin平台,网络上教程很多,也很杂乱,于是便整理一版自用。 主要根据NVIDIA Lidar AI Solution进行复现。并在此基础上进行补充 Orin平台: python:3.8 CUDA:11.4 torch:1.14.0 torchvision:0.15.1 TensorRT: 8.5.2.1 在Compile &&a…

Java并发编程实战 08 | 彻底理解Shutdown Hook

钩子线程&#xff08;Hook Thread&#xff09;简介 在一个 Java 应用程序即将退出时&#xff08;比如通过正常执行完成或通过用户关闭应用程序&#xff09;&#xff0c;通常需要进行一些清理操作&#xff0c;例如&#xff1a; 释放资源&#xff08;如文件句柄、网络连接&…