「C系列」C 指针及其应用案例

文章目录

  • 一、C 指针
    • 1. 指针的定义
    • 2. 指针的初始化
    • 3. 指针的解引用
    • 4. 指针的运算
    • 5. 动态内存分配
    • 6. 指针的NULL初始化
    • 7. 指针作为函数参数和返回值
    • 8. 指针数组和数组指针
    • 9. 多级指针
  • 二、C语言中有哪些内置的指针操作符
  • 三、常见应用案例
    • 1. 交换两个变量的值
    • 2. 数组与指针
    • 3. 字符串操作
    • 4. 链表操作
    • 5. 动态内存分配
  • 四、相关链接

在这里插入图片描述

一、C 指针

在C语言中,指针是一个非常重要的概念,它允许程序直接访问内存地址,并操作该地址上存储的数据。指针本身是一个变量,但它存储的不是实际的数据值,而是存储数据值的内存地址。

以下是关于C语言中指针的一些基本概念和用法:

1. 指针的定义

指针变量通常通过以下方式定义:

int *ptr;  // 定义一个指向int类型数据的指针变量ptr

这里的int *是一个类型,表示这是一个指向int类型数据的指针。

2. 指针的初始化

在定义指针变量后,通常需要将其初始化为一个有效的内存地址。这可以通过以下方式完成:

int x = 10;
int *ptr = &x;  // 将ptr初始化为x的地址

在这里,&是一个取地址运算符,它返回变量x在内存中的地址。

3. 指针的解引用

解引用指针意味着访问指针所指向的内存地址上的数据。这可以通过在指针变量前加*来实现:

int y = *ptr;  // 将ptr所指向的int值(即x的值)赋值给y

4. 指针的运算

指针可以进行一些基本的算术运算,如加法、减法等。但这些运算不是基于指针的值(即内存地址),而是基于指针所指向的数据类型的大小。例如,如果ptr是一个指向int的指针,那么ptr + 1将指向下一个int类型的内存位置。

5. 动态内存分配

在C语言中,可以使用malloccalloc等函数在运行时动态地分配内存,并将返回的内存地址存储在指针变量中。例如:

int *array = (int *)malloc(10 * sizeof(int));  // 分配一个包含10个int的数组的内存

注意:在使用完动态分配的内存后,应使用free函数释放内存,以避免内存泄漏。

6. 指针的NULL初始化

为了避免野指针(指向无效内存地址的指针),通常会将指针初始化为NULL:

int *ptr = NULL;

7. 指针作为函数参数和返回值

指针经常作为函数的参数和返回值,以实现数据的间接访问和修改。例如,一个交换两个整数值的函数可以接收两个指向整数的指针作为参数:

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

8. 指针数组和数组指针

  • 指针数组:一个数组,其元素是指针。
  • 数组指针:一个指针,指向数组的首个元素。

这两者在语法和用途上有所不同,需要仔细区分。

9. 多级指针

在C语言中,还可以定义指向指针的指针,即多级指针。例如,int **ptr是一个指向int指针的指针。多级指针在某些复杂的数据结构和算法中非常有用。

二、C语言中有哪些内置的指针操作符

在C语言中,与指针相关的内置操作符主要有以下几个:

  1. 取地址操作符(&)
  • 这个操作符用于获取变量的内存地址。
  • 示例:int x = 10; int *ptr = &x; 这里,&x 就是取变量 x 的地址,并将这个地址赋值给指针 ptr
  1. 解引用操作符(*)
  • 这个操作符用于访问指针所指向的内存地址中的数据。
  • 示例:int y = *ptr; 这里,*ptr 就是访问 ptr 所指向的内存地址上的数据,并将其赋值给变量 y
  • * 出现在声明中时,它表示指针的类型;但在表达式中,它表示解引用操作。
  1. 指针算术操作符(+ 和 -)
  • 这两个操作符用于指针的算术运算。
  • 当用于指针时,它们基于指针所指向的数据类型的大小进行运算。例如,对于指向 int 的指针,ptr + 1 会将指针向前移动一个 int 的大小。
  • 示例:ptr++ptr += 2 等都是有效的指针算术操作。
  1. 指针比较操作符(==、!=、<、<=、>、>=)
  • 这些操作符用于比较两个指针是否指向相同的内存地址,或者它们在内存中的相对位置。
  • 需要注意的是,只有当两个指针指向同一数组(或同一块内存区域)中的元素时,比较它们的大小才有意义。
  1. -> 操作符(结构体指针的成员访问)
  • 这个操作符用于通过结构体指针访问结构体的成员。
  • 示例:如果 struct_ptr 是一个指向结构体的指针,并且该结构体有一个名为 member 的成员,则可以使用 struct_ptr->member 来访问这个成员。
  1. . 操作符(结构体的成员访问)
  • 虽然这不是一个专门的指针操作符,但在与结构体和指针一起使用时,. 操作符用于通过结构体变量访问其成员。
  • 示例:如果 struct_var 是一个结构体变量,并且该结构体有一个名为 member 的成员,则可以使用 struct_var.member 来访问这个成员。

需要注意的是,除了上述操作符之外,还有其他一些操作符(如赋值操作符 =、自增/自减操作符 ++-- 等)也可以与指针一起使用,但它们并不是专门为指针设计的。

三、常见应用案例

C 语言中的指针具有广泛的应用,以下是一些常见的应用案例及其详细代码:

1. 交换两个变量的值

使用指针可以避免使用临时变量来交换两个变量的值。

#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    printf("Before swap: x = %d, y = %d\n", x, y);
    swap(&x, &y);
    printf("After swap: x = %d, y = %d\n", x, y);
    return 0;
}

2. 数组与指针

在 C 语言中,数组名实际上是一个指向数组首元素的指针。

#include <stdio.h>

void printArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]); // 也可以使用 *(arr + i)
    }
    printf("\n");
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    printArray(arr, size);
    return 0;
}

3. 字符串操作

在 C 语言中,字符串是通过字符数组实现的,而字符串操作经常涉及到指针。

#include <stdio.h>
#include <string.h>

void concat(char *dest, const char *src) {
    while (*dest) { // 找到 dest 字符串的末尾
        dest++;
    }
    while (*src) { // 复制 src 字符串到 dest 的末尾
        *dest++ = *src++;
    }
    *dest = '\0'; // 添加字符串结束符
}

int main() {
    char str1[50] = "Hello, ";
    char str2[] = "World!";
    concat(str1, str2);
    printf("%s\n", str1); // 输出: Hello, World!
    return 0;
}

4. 链表操作

链表是一种常见的数据结构,它的节点通常通过指针链接在一起。

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

void insert(Node **head, int data) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = data;
    newNode->next = *head;
    *head = newNode;
}

void printList(Node *head) {
    Node *current = head;
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

int main() {
    Node *head = NULL;
    insert(&head, 1);
    insert(&head, 2);
    insert(&head, 3);
    printList(head); // 输出: 3 2 1
    return 0;
}

5. 动态内存分配

使用 malloccallocrealloc 等函数在运行时动态地分配和重新分配内存。

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr = (int *)malloc(5 * sizeof(int));
    if (arr == NULL) {
        printf("Memory allocation failed\n");
        return 1;
    }
    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1;
    }
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    free(arr); // 释放内存
    return 0;
}

四、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C系列」C 简介
  4. 「C系列」C 基本语法
  5. 「C系列」C 数据类型
  6. 「C系列」C 变量及常见问题梳理
  7. 「C系列」C 常量
  8. 「C系列」C 存储类
  9. 「C系列」C 运算符
  10. 「C系列」C 判断/循环
  11. 「C系列」C 函数
  12. 「C系列」C 作用域规则
  13. 「C系列」C 数组
  14. 「C系列」C enum(枚举)

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

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

相关文章

SwiftUI中自定义Shape与AnimateableData的使用

上一篇文章主要介绍了一下在SwiftUI中如何自定义Shape&#xff0c;本篇文章主要介绍Shape中的 一个关键的属性AnimatableData&#xff0c;它用于定义可以被动画化的数据。通过实现 Animatable 协议&#xff0c;可以让自定义视图或图形响应动画变化。 AnimatableData 是 Animata…

flutter 环境搭建(windows)(先装 jdk 建议1.8起步)

1&#xff1a;先从 官网 下载一个合适版本的SDK 2&#xff1a;下载完成之后 解压到一个合适的盘符下面&#xff08;本文在 D 盘 3.10.0版本&#xff09; 3&#xff1b;双击 flutter_console.bat文件可以看到一些基本信息 4&#xff1a;配置环境 1.添加用户变量 FLUTTER_STORAGE…

DSSA(Domain-Specific Software Architecture)方法论

DSSA&#xff08;Domain-Specific Software Architecture&#xff09;方法论是一种针对特定问题领域的软件架构设计方法。在软件开发中&#xff0c;有些问题在特定领域是共通的&#xff0c;这些问题可以通过通用的抽象和解决方案来处理。DSSA方法论正是利用这一特点&#xff0c…

Vue3、Element Plus使用v-for循环el-form表单进行校验

在开发中遇到了这样一个需求 有一个form是通过v-for生成出来的&#xff0c;并且数量不确定&#xff0c;每个表单中的字段都需要做校验&#xff0c;就将自己的解决方法记录了下来。 完整代码如下 <template><div class"for-form"><el-button type&quo…

Class-Aware Self-Distillation for Remote SensingImage Scene Classification

这篇文章提出了一种新的蒸馏方式&#xff0c;由于遥感场景图像具有类间相似性和类内多样性的特点&#xff0c;这篇文章试图解决这个问题。通过三个共享权重的分支&#xff0c;同时输入三张图片&#xff0c;其中两张类别相同的图片&#xff0c;一张类别不同但地物特征相似的图片…

AcWing 477:神经网络 ← 拓扑排序+链式前向星

【题目来源】https://www.acwing.com/problem/content/479/【题目描述】 人工神经网络&#xff08;Artificial Neural Network&#xff09;是一种新兴的具有自我学习能力的计算系统&#xff0c;在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。 对神经网络的研究…

179.二叉树:合并二叉树(力扣)

代码解决 /*** 二叉树节点的定义。* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, Tre…

记录在京东云ICP备案全流程,适用于网站备案和APP备案

记录一下在京东云ICP备案全流程&#xff0c;本文适用用于网站域名备案和APP备案&#xff0c;域名备案和APP备案其实差不多&#xff0c;就是服务类型选择网站或APP的区别&#xff0c;阿腾云整理详细京东云服务器备案全流程&#xff0c;大家可以收藏下&#xff0c;非常详细的备案…

爬虫相关面试题

一&#xff0c;如何抓取一个网站&#xff1f; 1&#xff0c;去百度和谷歌搜一下这个网站有没有分享要爬取数据的API 2, 看看电脑网页有没有所需要的数据&#xff0c;写代码测试调查好不好拿&#xff0c;如果好拿直接开始爬取 3&#xff0c;看看有没有电脑能打开的手机网页&a…

Unity与Js通信交互

目录 1.Js给Unity传递消息 2.Unity给Js传递消息 简介: Unity 与 JavaScript 通信交互是指在 Unity 项目中实现与 JavaScript 代码进行数据交换和功能调用的过程。 在 Unity 中&#xff0c;可以通过特定的接口和技术来与外部的 JavaScript 环境进行连接。这使得 Unity 能够利…

怎么修改Visual Studio Code中现在github账号

git config --global user.name “你的用户名” git config --global user.email “你的邮箱” git config --global --list git push -u origin your_branch_name git remote add origin

鸿蒙轻内核A核源码分析系列五 虚实映射(2)虚实映射初始化

2、 虚拟映射初始化 在文件kernel/base/vm/los_vm_boot.c中的系统内存初始化函数OsSysMemInit()会调用虚实映射初始化函数OsInitMappingStartUp()。该函数代码定义在文件arch/arm/arm/src/los_arch_mmu.c&#xff0c;代码如下。⑴处函数使TLB失效&#xff0c;清理虚实映射缓存…

基于STM32的简易智能家居设计(嘉立创支持)

一、项目功能概述 1、OLED显示温湿度、空气质量&#xff0c;并可以设置报警阈值 2、设置4个继电器开关&#xff0c;分别控制灯、空调、开关、风扇 3、设计一个离线语音识别系统&#xff0c;可以语音控制打开指定开关、并且可以显示识别命令词到OLED屏上 4、OLED实时显示&#…

在k8s中部署Elasticsearch高可用集群详细教程

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《洞察之眼&#xff1a;ELK监控与可视化》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、Elasticsearch简介 2、为什么在k8s中部署elasti…

计算机毕业三年的我,辞职两次后找不到工作回家,此时是真的羡慕有手艺在手的人

栀子花香&#xff0c;弥漫在空气中&#xff0c;却掩盖不了内心的苦涩。 半年&#xff0c;两份工作&#xff0c;两次裸辞&#xff0c;我&#xff0c;又成了一个身无分文的“废人”。 曾经&#xff0c;我也是人人羡慕的互联网人&#xff0c;月薪6K&#xff0c;过着“955”的“神…

LeetCode | 27.移除元素

这道题的思路和26题一模一样&#xff0c;由于要在元素组中修改&#xff0c;我们可以设置一个index表示目前要修改原数组的第几位&#xff0c;由于遍历&#xff0c;访问原数组永远会在我们修改数组之前&#xff0c;所以不用担心数据丢失的问题&#xff0c;一次遍历数组&#xff…

别再忽视数组排序的重要性了

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

JavaSE---类和对象(上)

1. 面向对象的初步认知 1.1 什么是面向对象 Java是一门纯面向对象的语言(Object Oriented Program&#xff0c;简称OOP)&#xff0c;在面向对象的世界里&#xff0c;一切皆为对象。 面向对象是解决问题的一种思想&#xff0c;主要依靠对象之间的交互完成一件事情。用面向对象…

kettle从入门到精通 第六十八课 ETL之kettle kettle随机数生成的一些方案

1、在做ETL数据抽取的时候&#xff0c;会用到生成随机数的功能&#xff0c;今天我们一起来学习下如何生成随机数据。如下图所示 2、将生成随机数拉倒画布即可&#xff0c;然后设置字段名称和选择合适的类型&#xff0c;如下图所示&#xff1a; 类型&#xff1a; 随机数字&…

自动同步库数据——kettle开发36

kettle中的那些人工智能。 一、kettle的AI能力目录 跨库同步 2.自动开发 3.自动优化 二、AI实例 1、跨库同步 sqlsever表同步至oracle数据库 1.1源库sqlserver 1.2目标库oracle 1.3可视化跨库同步 使用多表复制向导 选择跨库的表&#xff0c;下一步下一步&#xff0c;即可…