C语言基础(十一)

news2024/11/13 7:53:06

1、指针:

C语言中的指针是一种非常重要的数据类型,可以直接访问和操作内存地址。指针存储变量的内存地址,而不是变量的值本身。通过使用指针,可以灵活地控制数据的存储和访问,实现复杂的数据结构如链表、树。

定义指针:
在C语言中,指针是通过在变量类型前加上星号(*)定义的。例如,int *ptr; 表示 ptr 是一个指向 int 类型数据的指针。

初始化指针:
使用指针之前,需要将其初始化为某个变量的地址或 NULL(表示指针不指向任何有效地址)。
例如,int var = 10; int *ptr = &var; ,&var 是取地址运算符,获取 var 的地址,并将其赋值给 ptr。

通过指针访问数据:
通过解引用指针(在指针前加星号),可以访问指针所指向的数据。例如,*ptr = 20; 将 var 的值修改为 20。

指针的算术运算:
指针的算术运算主要是指针的加减运算,以指针指向的数据类型的大小为单位进行。
例如,如果 ptr 是指向 int 的指针,ptr+1 将使 ptr 指向下一个 int 类型的存储位置。

指针的关系运算:
可以比较两个指针是否相等或不等,以及它们之间的顺序关系(前提是两个指针指向同一个数组的元素或指向数组之后的位置)。

指针的用途:
动态内存分配:通过 malloc、calloc 和 realloc 等函数,可以在堆(heap)上动态地分配内存,这些函数返回指向分配的内存的指针。

数组和字符串的访问:
在C语言中,数组名实际上是数组首元素的地址,因此可以使用指针遍历数组或字符串。

函数参数:
通过指针,可以将变量的地址传递给函数,允许函数修改传递给它的参数的值。

实现复杂数据结构:
如链表、树、图等,这些数据结构中的元素通常通过指针相互连接。

指针在使用前必须初始化,否则它们可能指向不确定的内存位置,导致程序崩溃或不可预测的行为。
指针运算时不要越界,即不要访问指针未指向的内存区域。
使用完动态分配的内存后,应通过 free 函数释放,以避免内存泄漏。
 

2、指针变量:

指针变量在C语言中是一种特殊的变量类型,用于存储内存地址而不是直接存储数据值。通过使用指针变量,程序可以间接地访问和操作存储在内存中的数据。指针变量提供了一种强大的机制管理内存,特别是在需要动态内存分配、数据结构操作或系统级编程时。

指针变量的定义
指针变量的定义包括指定指针所指向的数据类型。例如:int *ptr; 定义一个名为 ptr 的指针变量,它指向一个整型(int)数据。* 表示 ptr 是一个指针,而 int 指定了指针所指向的数据类型。

指针变量的赋值
指针变量可以被赋予两个类型的值:

地址:指针最常见的用途是存储某个变量的地址。通过取地址操作符 & 实现,例如 :ptr = &a; 将变量 a 的地址赋给指针 ptr。
另一个指针:指针也可以被赋予另一个同类型指针的值,从而实现指针的传递或赋值。

指针变量的间接访问
指针变量的主要操作是间接访问,即访问指针所指向的内存位置的值。通过解引用操作符 * 实现,例如: *ptr 表示访问 ptr 所指向的值。

指针变量的运算
指针变量支持几种特殊的运算,主要是指针算术运算:

指针加减:指针可以进行加减运算,但加减的不是指针本身的值,而是指针所指向类型的大小。例如,对于指向整型的指针 int *ptr,ptr + 1 实际上是将 ptr 的值增加了一个整型的大小(通常是4或8个字节,取决于编译器和平台)。


指针比较:两个指针可以进行比较运算,以检查它们是否指向内存中的相同位置或相对位置。

指针必须被初始化后才能使用,以避免指向不确定的内存位置。
指针解引用时,必须确保指针指向了一个有效的内存位置,否则可能会导致未定义行为,包括程序崩溃。
指针运算时,要注意指针所指向的数据类型,因为不同的数据类型在内存中占用的空间大小是不同的。

测试代码1:

#include "date.h"
#include <stdio.h>  
int main() {  
    int time = getTime();
    int var = 10; // 定义一个整型变量var  
    int *ptr; // 定义一个指向整型的指针ptr  
  
    // 将指针ptr指向var的地址  
    ptr = &var;  
    
    // 打印var的地址 
	// %p 是打印指针(即地址)的格式说明符   
    printf("The address of var is: %p\n", &var);  
    
    // 打印var的地址,将 &var 强转换为 (void*) 
    printf("The address of var is: %p\n", (void*)&var);  
    
     // 通过ptr打印var的地址(因为ptr已经存储了var的地址)  
    printf("The address of var through ptr is: %p\n", ptr);  
    
    // 通过ptr打印var的地址(因为ptr已经存储了var的地址),强转换为 (void*) 
    printf("The address of var through ptr is: %p\n", (void*)ptr);  
       
    return 0;  
}

运行结果如下:

 

测试代码2:

#include "date.h" 
#include <stdio.h>  
//指针的访问 
int main() {  
    int time = getTime();
    int value = 10; // 定义一个整型变量value,并初始化为10  
    int *ptr; // 定义一个指向整型的指针ptr  
  
    // 将ptr指向value的地址  
    ptr = &value;  
  
    // 通过指针直接访问value的值,并打印出来
	// *ptr 表示直接访问 ptr 指针所指向的内存地址中的值。  
    printf("The value of value through pointer is: %d\n", *ptr);  
    // 地址是这个 
    printf("The address is: %d\n", ptr);  
    
    // 通过指针直接修改value的值  
    *ptr = 20;  
  
    // value的值已经被修改  
    printf("The new value of value is: %d\n", value);  
  
    return 0;  
}

运行结果如下:

 

测试代码3:

#include "date.h" 
#include <stdio.h>  
  
int main() {  
    int tiem = getTime();
    // int 类型  
    int intVar = 10;  
    int *ptrInt = &intVar;  
    printf("The value of intVar through ptrInt: %d\n", *ptrInt);  
  
    // char 类型(使用字符串)  
    char str[] = "Hello, World!";  
    char *ptrChar = str;  
    printf("The first character of the string: %c\n", *ptrChar);  
    // 遍历字符串(指针运算)  
    while (*ptrChar != '\0') {  
        printf("%c", *ptrChar);  
        ptrChar++; // 指针运算:移动到字符串的下一个字符  
    }  
    printf("\n");  
  
    // float 类型 
    float floatVar = 3.14f;  
    float *ptrFloat = &floatVar;  
    printf("The value of floatVar through ptrFloat: %f\n", *ptrFloat);  
  
    // float数组,指针的算术运算  
    float floatArr[] = {1.1f, 2.2f, 3.3f};  
    float *ptrFloatArr = floatArr;  
    printf("The first element of floatArr: %f\n", *ptrFloatArr);  
    ptrFloatArr++; // 指针运算:移动到数组的下一个元素  
    printf("The second element of floatArr: %f\n", *ptrFloatArr);  
  
    return 0;  
}

运行结果如下:

 

测试代码4:

#include "date.h" 
#include <stdio.h>  
  
int main() {  
    int time = getTime();
    int a = 10; // 定义一个整型变量a  
    int b = 20; // 定义一个整型变量b  
    int *ptrA = &a; // 创建一个指向a的指针ptrA  
    int *ptrB = &b; // 创建一个指向b的指针ptrB  
  
    // 输出a和b的地址  
    printf("Address of a: %p\n", (void *)&a);  
    printf("Address of b: %p\n", (void *)&b);  
  
    // 比较ptrA和ptrB(即a和b的地址)是否相同  
    if (ptrA == ptrB) {  
        printf("Addresses of a and b are the same.\n");  
    } else {  
        printf("Addresses of a and b are different.\n");  
    }  
  
    // 大多数情况下,a和b会被分配在栈上的不同位置,  
    // 通过某种方式(如数组元素),让它们共享相同的内存地址,比较就会返回true。    
  
    // 使用数组:  
    int arr[2] = {10, 20};  
    int *ptrArrA = &arr[0]; // 指向arr的第一个元素  
    int *ptrArrB = &arr[1]; // 指向arr的第二个元素  
  
    // 比较ptrArrA和ptrArrB(即arr[0]和arr[1]的地址)是否相同  
    // 比较两个数组元素的地址,当然不同。  
    if (ptrArrA == ptrArrB) {  
        printf("Addresses of arr[0] and arr[1] are the same. (This will not happen.)\n");  
    } else {  
        printf("Addresses of arr[0] and arr[1] are different.\n");  
    }  
  
    // 比较&arr[0]和&arr[0],则相同 
    if (&arr[0] == ptrArrA) {  
        printf("Addresses of &arr[0] and ptrArrA are the same.\n");  
    }  
  
    return 0;  
}

运行结果如下:

 

 

 

 

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

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

相关文章

C++操作excel,即使函数设置了不备份,但保存后,excel依然会自动生成备份文件的原因分析,及如何来禁止自动备份

开发环境 操作系统&#xff1a;windows 10 编译器&#xff1a;Visual Studio 2010、2015、2017、2022 office 2016、2019、2021 wps 2019、2024 问题描述 通过C操作excel&#xff0c;保存后&#xff0c;excel会自动生成备份文件。 void CExcelDemoDlg::OnBnClickedButton1() …

Open3D mesh 隐藏点移除

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2去除隐藏点后的点云 Open3D点云算法汇总及实战案例汇总的目录地址&#xff1a; Open3D点云算法与点云深度学习案例汇总&#xff08;长期更新&…

力扣 128. 最长连续序列

题目描述 我的思路 我的思路比较暴力&#xff0c;就是首先将数组从小到大进行排序&#xff0c;然后再依次遍历判断序列是否连续并时时更新连续序列的最长长度。比如示例1&#xff1a;nums [100, 4, 200, 1, 3, 2]&#xff0c;第一步先将数组进行排序得到sort_nums [1, 2, 3,…

Android Studio(3) 使用 Kotlin DSL和 Gradle 8.7 打包远程库到 AAR 的自定义方法

背景介绍 在 Gradle 7.3 及更早版本中,通常使用 com.kezong.fat-aar 插件来打包远程库到 AAR 中,随着 Gradle 的不断升级,尤其是到 8.7 版本后,Kotlin DSL开发逐渐成为主流,fat-aar 社区没有更新,插件的兼容性问题逐渐显现。我探索一种新的自定义方法,能够在 Kotlin DS…

js逆向学习

目前本人大三下&#xff0c;想要学习js逆向同学的可以联系我&#xff1a;2697279763qq.com 上面是本人做的一些比较复杂的项目&#xff0c;还有很多简单的项目&#xff0c;这里给出图片。 还有一些简单的js逆向。 教你各种补充环境&#xff0c;各种js算法&#xff0c;教你各种底…

(软工) 四代软件架构

&#x1f522;前言 当今软件架构中&#xff0c;拥有四代软件架构。这四个都是基于所在时代&#xff0c;技术&#xff0c;需求等多种因素应运而生的。 在未来是否会有第五代软件架构&#xff0c;无人可知。笔者大胆推测&#xff0c;这第五代很可能与人工智能的大语言模型有关&…

Windows—UDP编程

Client骨架&#xff1a; #include <iostream> #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib")int main() {//启动Winsock DLLWORD wVersionRequested MAKEWORD(2, 2);WSADATA lpWSAData;WSAStartup(wVersionRequested, &lpWSAData);//…

【数据结构】线性表的顺序表示(顺序表的定义和基本操作)

计算机考研408-数据结构笔记本之——第二章 线性表 2.2 线性表的顺序表示&#xff08;顺序表的定义和基本操作&#xff1a;初始化/插入/删除/查找&#xff09; 2.2.1 顺序表的定义 1.定义 顺序表是线性表的顺序存储。 所谓顺序存储&#xff0c;就是把逻辑上相邻的元素存储在物…

预约咨询小程序搭建开发,uniapp前端,PHP语言开发

目录 前言&#xff1a; 一、预约小程序搭建功能介绍 二、示例代码片段 前言&#xff1a; 预约咨询小程序适合需付费咨询和交流的场景&#xff1a;比如讲师,摄影,婚庆&#xff0c;美发,律师,心理等等支持商家入驻支持视频、图文、线下、电话等方式在线支付咨询。 一、预约小程…

代码随想录 刷题记录-14 回溯(3)字符串、子集、排列问题

字符串 1.131.分割回文串 思路 本题这涉及到两个关键问题&#xff1a; 切割问题&#xff0c;有不同的切割方式判断回文 切割问题&#xff0c;也可以抽象为一棵树形结构&#xff0c;如图&#xff1a; 回溯三部曲 递归函数参数 全局变量数组path存放切割后回文的子串&…

《计算机操作系统》(第4版)第5章 虚拟存储器 复习笔记

第5章 虚拟存储器 一 、虚拟存储器概述 1. 常规存储管理方式的特征和局部性原理 (1)特征 ①一次性。 ②驻留性。 (2)局部性原理 局部性原理表现在时间局部性和空间局部性两方面。 2.虚拟存储器的定义和特征 (1)虚拟存储器的定义 虚拟存储器是指具有请求调入功能和置换功能&…

java之表格数据存储

java之表格数据存储 摘要表格数据存储javabean 介绍javabean 设计类表格数据存储 摘要 本博客主要讲述java如何存储表格数据。 表格数据存储 在解决实际问题的时候&#xff0c;需要涉及到如何存储表格的数据&#xff0c;这里讲述了一种使用javabean的方法存储表格 javabea…

STM中的I2C

常见的几种通信接口 I2C总线定义 定义 I2C - Inter-Integrated Circuit&#xff1a;两线式 串行总线&#xff1a;说明处理器和外设之间只需两根信号线&#xff0c;分别是SCL时钟控制信号线和SDA数据线 SCL&#xff08;serial clock line&#xff09; 时钟控制信号线&#xff…

makefile文件基本语法

一、makefile文件基本介绍 Makefile 文件是 make 工具使用的配置文件&#xff0c;它定义了如何自动化构建项目的规则和命令。Makefile 文件的主要作用是指定如何编译和链接程序&#xff0c;以及管理文件之间的依赖关系&#xff0c;从而实现高效的构建过程。 1.1 Makefile 的基…

【FreeRTOS】队列实验-分发数据给多个任务(赛车游戏)

目录 0 前言1 队列实验_分发数据给多个任务(赛车游戏)2 赛车游戏2.1 game.c2.2 注册队列2.3显示汽车2.4隐藏汽车2.5 CarTask2.6 car_game2.7 MX_FREERTOS_Init 3 总结 0 前言 学习视频&#xff1a; 【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS&#xff08;FreeRTOS教…

如何用Python实现山东省旅游数据爬虫与K-means满意度分析

&#x1f393; 作者&#xff1a;计算机毕设小月哥 | 软件开发专家 &#x1f5a5;️ 简介&#xff1a;8年计算机软件程序开发经验。精通Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等技术栈。 &#x1f6e0;️ 专业服务 &#x1f6e0;️ 需求定制化开发源码提…

AI一键视频多语言配音/翻译工具:打造无缝多语言视频体验

在全球化的今天,视频内容的传播不再受限于地域和语言。然而,如何高效地将视频内容翻译成多种语言并保持其自然度和流畅性,一直是业界面临的挑战。为了解决这一难题,我们推出了一款智能视频多语言AI配音和翻译工具——Linly Dubbing。该工具基于YouDub-webui的灵感进行了创新…

开源:cuda studio云原生一站机器学习、深度学习、大模型AI平台

文章目录 1、 cuda studio云原生一站机器学习、深度学习、大模型AI平台2、网址 1、 cuda studio云原生一站机器学习、深度学习、大模型AI平台 cube studio开源云原生一站式机器学习/深度学习/大模型AI平台&#xff0c;支持sso登录&#xff0c;多租户&#xff0c;大数据平台对接…

3级线性反馈移位寄存器在C3=1时可有4种线性反馈函数,设其初始状态为(a1,a2,a3)=(1,0,1),求各线性反馈函数的输出序列及周期

标题是题目 题解 1.补充知识 2.分析四种情况&#xff1a; 结合我所给的反馈数公式以及a31&#xff0c;可以得到反馈函数为: fC1*a3⊕C2*a2⊕C3*a1C1*a3⊕C2*a2⊕a1 附&#xff1a;别把初始状态为&#xff08;a1,a2,a3&#xff09;(1,0,1)带入&#xff0c;因为a1,a2,a3的值…

小程序学习day11-生命周期函数、组件所在页面的生命周期、自定义组件的插槽、自定义组件的父子通信

40、自定义组件&#xff08;续&#xff09;&#xff08;续&#xff09; &#xff08;10&#xff09;生命周期函数 1&#xff09;小程序里的全部生命周期函数 ①created&#xff08;在组件刚被创建时执行&#xff09;&#xff08;被创建&#xff0c;但未被放入页面&#xff09…