C语言基础(十一)

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.mfbz.cn/a/871874.html

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

相关文章

Redis (day 3)

一、通过jedis连接数据库 1.首先导入依赖 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>5.1.0</version></de…

Mac系统安装Homebrew【已成功】

1、正常安装失败原因 1.1命令行安装失败 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 原因 没挂&#x1fa9c;&#xff0c;不过我挂了梯子安装很多次也还是失败&#xff0c;所以可能是网站原因 1.2、网…

MyBatis进阶-1-面向接口编程

通过 MyBatis 底层自动创建接口实现类&#xff0c;我们可以直接对接口的方法进行编程 若简单的 sql 语句可以使用注解的方式进行&#xff0c;复杂的查询建议使用 xml 文件编写语句 注解使用时直接在接口的方法上加上对应语句的注解即可&#xff0c;而使用 xml 需要在文件中的…

ES6解构赋值详解;全面掌握:JavaScript解构赋值的终极指南

目录 全面掌握&#xff1a;JavaScript解构赋值的终极指南 一、数组解构赋值 1、基本用法 2、跳过元素 3、剩余元素 4、默认值 二、对象解构赋值 1、基本用法 2、变量重命名 3、默认值 4、嵌套解构 三、复杂的嵌套结构解构 四、函数参数解构赋值 1、对象解构作为函…

Jenkins汉化配置详解

Window安装构建神器Jenkins Window安装构建神器Jenkins详细教程-CSDN博客DevOps&#xff0c;CI&#xff0c;CD&#xff0c;自动化简单介绍选择其他需要和Jenkins一起安装的服务&#xff0c;点击Next。https://blog.csdn.net/qq_37237487/article/details/141299623 登录进入J…

【机器学习】CNN的基本架构模块

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 CNN的基本架构模块1. 引言2. 卷积层2.1 基本原理2.2 卷积层的特性2.3 卷积层的超…

SQL,解析 json

Google BigQuery数据库的data表存储了若干多层的Json串&#xff0c;其中一条形如&#xff1a; [{"active":true,"key":"key1","values":[{"active":true,"value":"value1"}]},{"active":tru…

Java巅峰之路---进阶篇---面向对象(二)

Java巅峰之路---进阶篇---面向对象&#xff08;二&#xff09; 多态介绍多态调用成员的特点多态的优势、弊端以及解决方案综合练习 包和final包的介绍使用其他类的规则&#xff08;导包&#xff09;final关键字final的用途常量 权限修饰符和代码块权限修饰符的介绍四个权限修饰…

Halo个人博客Docker部署结合内网穿透为本地站点配置公网地址远程访问

文章目录 前言1. Docker部署Halo1.1 检查Docker版本如果未安装Docker可参考已安装Docker步骤&#xff1a;1.2 在Docker中部署Halo 2. Linux安装Cpolar2.1 打开服务器防火墙2.2 安装cpolar内网穿透 3. 配置Halo个人博客公网地址4. 固定Halo公网地址 前言 本文主要介绍如何在Cen…

C#学习第二节课 ,伤害计算

伤害计算 我一直好奇游戏的伤害计算是怎么计算并输出的,这第二节课利用学过的初级语法,Console.WriteLine,Console.ReadLine(),以及基础变量,int,string 和if 判断 组合,来实现打印一下伤害计算吧! 老规矩 先上结果图 代码区域 namespace hello01 {internal class Program …

望繁信科技荣膺上海市浦东新区博士后创新实践基地称号

近日&#xff0c;上海望繁信科技有限公司&#xff08;简称“望繁信科技”&#xff09;凭借在大数据流程智能领域的卓越表现&#xff0c;成功入选上海市浦东新区博士后创新实践基地。这一荣誉不仅是对望繁信科技创新能力和技术实力的高度认可&#xff0c;也标志着公司在推动产学…

EasyCVR视频汇聚平台构建远程安防监控:5大亮点解析,助力安防无死角

随着科技的飞速发展&#xff0c;远程安防监控系统已经成为现代社会中不可或缺的一部分&#xff0c;无论是在小区、公共场所还是工业领域&#xff0c;安防监控都发挥着至关重要的作用。而EasyCVR作为一款功能强大的视频监控综合管理平台&#xff0c;其在构建远程安防监控系统方面…

Qt 学习第六天:页面布局

如何设计页面&#xff1f; 有个类似沙盒模式的玩法&#xff0c;Qt Widget Designer可以更好的帮助我们设计页面 点击.ui文件进入 右上方可以看到四种常见的布局&#xff1a; 四种布局 &#xff08;一&#xff09;水平布局horizontalLayout&#xff1a;QHBoxLayout H 是 hori…

算法之工程化内容(3)—— Docker常用命令

目录 1. 配置docker镜像加速 2. 创建镜像docker-name 3. 查看正在运行的镜像 4. 拉取镜像 5. 运行镜像 6. 停止/启动指定 id 的容器 7. 删除指定 id 的镜像/容器 8. docker发布和部署 (推荐教程&#xff1a;&#x1f69a; 发布和部署 - Docker 快速入门) 1. 配置docke…

【蓝桥杯集训100题】scratch时间计算 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第26题

目录 scratch时间计算 一、题目要求 编程实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 2、详细过程 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、python资料 scratc…

【网络】UDP和TCP之间的差别和回显服务器

文章目录 UDP 和 TCP 之间的差别有连接/无连接可靠传输/不可靠传输面向字节流/面向数据报全双工/半双工 UDP/TCP API 的使用UDP APIDatagramSocket构造方法方法 DatagramPacket构造方法方法 回显服务器&#xff08;Echo Server&#xff09;1. 接收请求2. 根据请求计算响应3. 将…

AdMob聚合平台

Google Admob产品介绍 Google给开发者提供了3款用于流量变现的产品&#xff0c;分别是AdMob&#xff0c;通过应用内广告帮助App开发者变现&#xff1b;AdSense&#xff0c;通过网站广告帮助所有者变现&#xff1b;Google Ads Manager&#xff0c;通过全面管理和优化广告资源&a…

[ICLR-24] LRM: Large Reconstruction Model for Single Image to 3D

[pdf | proj | code] 本文首次提出大型重建模型&#xff08;Large Reconstruction Model, LRM&#xff09;&#xff0c;实现5s内对单图物体的3D重建。在128张A100&#xff08;40G&#xff09;上训练30 epochs。 LRM包含三个部分&#xff0c;具体框架如下&#xff1a; 图片编码…

亚马逊测评号生存法则:如何抵御亚马逊封号风波?

距离黑五购物狂欢节还剩99天&#xff0c;相信各位商家都在紧锣密鼓的筹备相关事宜&#xff0c;然而&#xff0c;亚马逊的封号风波再次席卷而来。那如何在这场风暴中让亚马逊矩阵测评号安全航行亦或是脱颖而出呢&#xff1f;本文将给你一个答案&#xff0c;并帮助你的亚马逊店铺…

【java计算机毕设】足浴城消费系统小程序MySQL ssm vue uniapp maven项目设计源代码 编程语言 小组课后作业 寒暑假作业

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】足浴城消费系统小程序MySQL ssm vue uniapp maven项目设计源代码 编程语言 小组课后作业 寒暑假作业 2项目介绍 系统功能&#xff1a; 足浴城消费系统小程序包括管理员、用户、商家三种角色。 管理员功能&…