C语言——初识指针

C语言,初识指针 指针,存在于C语言中,用途广泛。有了它就可以直接使用地址找到存储数据的空间直接修改,或者使用。那么在学习指针之前我一直有一个疑惑,那就是为什么要有指针?函数的内容可以直接通过名字直接访问,为什么还需要绕一圈?这不是更复杂了吗?事实上指针给我们提供了许多便利,接下来就来具体介绍什么是指针,以及指针的作用。 阅读详情

一、什么是指针?

指针(Pointer)是编程语言中一种重要的数据类型它,它用于存储变量的内存地址。换句话说,指针指向内存中的某个位置,其内容就是地址,这个地址指向存储的数据,程序可以直接访问和操作内存中的数据,这为动态内存分配、函数传参、数组访问等操作提供了便利和灵活性。总的来说,指针是一种允许直接操作内存地址和数据的数据类型,是实现诸多复杂数据结构和高级编程技术的重要基础。

二、指针变量和地址

在C语言中,指针是存储另一个变量内存地址的变量。每个变量在内存中都有一个地址,而指针存储了该地址,因此可以说指针指向该变量所在的内存地址。

当你创建一个指针变量并将其指向另一个变量时,该指针变量将包含另一个变量的内存地址。通过指针,可以访问和操作存储在该内存位置上的数据。

在内存方面,指针本身也需要存储在内存中。指针变量的大小取决于系统架构,在32位系统中为4字节,在64位系统中为8字节。

2.1指针变量

指针变量是一种特殊类型的变量,它存储的数值时内存地址。换句话说,指针变量包含了一个指向内存中特定位置的地址,而不是实际的数据。通过指针变量,程序可以直接地访问和操作内存中地数据。

在C语言中,声明指针变量时需要指定所指向的数据类型,这样编译器就知道在解引用时应该读取多少个字节的数据。指针变量的声明通常使用下面的语法:

int *ptr //声明一个整型指针。*说明ptr是指针变量,int说明ptr指向的是整型类型的对象。

2.2取地址操作符&

在C语言中,取地址操作符用&符号表示。当它与一个变量一起使用时,会返回该变量的所占内存地址较小的字节的地址,只要知道了第一个字节的地址,就可以根据变量的类型决定访问多少个字节的数据。

2.3解引用操作符*

在C语言中,解引用操作符*用于访问指针指向的内存地址上存储的值。换句话说,通过解引用操作符,我们可以从指针所指向的内存位置中读取或写入数据。

以下是一个简单示例,说明了指针和内存地址之间的关系:

#include<stdio.h>

int main()
{
    int num = 10; //定义一个整型变量
    int *ptr; //定义一个指针变量

    ptr=&num; //将指针指向num的地址

    printf("num的值:%d\n", num);
    printf("num的地址:%p\n", &num);
    printf("ptr存储的地址:%p\n", ptr);
    printf("ptr指向的值:%d\n", *ptr);

    return 0;
}

三、指针变量类型的意义 

3.1指针的解引用

指针变量的类型在C语言中具有重要意义。指针变量的类型决定了指针所指向的内存区域应如何解释和操作。

类型的意义在于指定了指针解引用时应该读取多少字节的数据。例如,如果一个指针声明位指向整数类型(int *ptr),则在解引用操作时,它会读取4个字节的数据。这种指定类型的方式允许编译器知道如何解释指针所指向的内存。

举例:

#include<stdio.h>

int main()
{
    int n=0x11223344;
    char *pc=(char *)&n;
    *pc=0;

    return 0;
}

//通过调试我们可以观察到,以上代码只会将n的第一个字节改为0。

3.2指针+-整数

在C语言中,指针与整数相加减是一种常见的操作,它可以用于移动指针指向的内存位置。这种操作的结果取决于指针所指向的数据类型,因为不同类型的数据占用的内存空间大小是不同的。

假设有一个指向某个数据类型的指针ptr,那么ptr+n的结果哦是将指针向后移动n个元素大小的内存空间,即ptr将指向从原始位置开始向后第n个元素的位置。同样的,ptr-n将会将指针向前移动n个元素大小的内存空间。

下面是一个示例,演示了指针与整数相加的操作:

#include<stdio.h>

int main()
{
    int arr[]={10,20,30,40,50};
    int *ptr=&arr[0];// 指针指向数组第一个元素的指针

    printf("初始位置:%p\n", ptr);

    ptr = ptr + 2; // 移动指针到数组的第三个元素
    printf("移动两个位置后:%p\n", ptr);

    return 0;
}

注:需要谨慎使用指针的偏移操作,确保不会越界访问或者指向无效的内存地址。 

3.3void*指针

void*是C语言中一种特殊类型的指针,被称为“无类型指针”。void*可以指向任意类型的数据,因为它的类型被声明为“void”,即没有具体的数据类型。这使得void*具有非常大的灵活性,可以用来实现泛型的数据结构和函数。

需要注意的是,由于编译器无法检查指针指向的数据类型是否匹配,因此,在使用void*指针时,需要确保在解引用之前将其转换为正确的类型。

下面是一个简单的示例,展示了void*指针的基本用法:

#include <stdio.h>

int main() 
{
    int num = 10;
    float f = 3.14;

    void *ptr; // 声明一个 void* 指针

    ptr = &num; // void* 指针指向 int 类型的变量
    printf("指向整数的指针,值为: %d\n", *(int *)ptr); // 解引用时需要将 void* 转换为正                            确的类型

    ptr = &f; // void* 指针指向 float 类型的变量
    printf("指向浮点数的指针,值为: %f\n", *(float *)ptr); // 解引用时需要将 void* 转换为正确的类型

    return 0;
}

总之,void*指针提供了一种非常灵活的机制来处理不同类型的数据,但同时也需要程序员对数据的类型进行严格的管理和转换。

四、const修饰指针

4.1const修饰变量

 在C语言中,可以使用关键字const来修饰变量,从而创建一个常量。被const修饰的变量表示其数值在初始化后不可被修改。这种修饰对于确保数据的不可变性非常有用,并且可以帮助提高代码的可读性和可维护性。

以下是const修饰变量的基本用法:

const int AGE = 30; // 声明一个整型常量
const float PI = 3.14; // 声明一个浮点型常量

int main() 
{
    const int MONTHS_IN_YEAR = 12; // 声明一个局部作用域的整型常量
    // AGE = 40; // 这里会导致编译错误,因为常量不可修改

    return 0;
}

在上面的例子中,AGE、PI和MONTH_IN_YEAR都是被修饰为常量的变量,它们在定义后不可以被修改。任何对这些变量的修改操作都将导致编译错误。

另外,const修饰符也可以用于函数参数,指定参数为只读,并防止在函数内部修改它们的值。这在函数参数传递过程中可以提供额外的安全性。

注:如果我们使用的是变量的地址去修改n,可以操作成功,但这打破了语法规则。

4.2const修饰指针变量

 当const用于修饰指针变量时,它可以有两种不同的用法:一种是将指针本身声明为常量,另一种是将指针指向的数据声明为常量。

将指针本身声明为常量:

int num = 5;
int *const ptr = &num;

在上述代码中,ptr被声明为一个常量指针,它指向num的地址,并在程序的执行过程中不能指向其它位置。这一位置ptr本身的值(即存储的地址)是不可更改的。

将指针指向的数据声明为常量:

int num1 = 10;
const int *ptr1 = &num1;

在上述代码中,ptr1是一个指向整数的指针,但由于被const修饰,它指向的数据是常量,不能通过ptr1来修改num1的值。

将指针本身和指针指向的数据都被声明为常量:

const int *const ptr2 = &num;

在上述代码中,ptr2是一个常量指针,它指向的数据也是常量,因此既不能更改ptr2的指向,也不能通过ptr2来修改它所指向的数据。 

五、野指针

“野指针”是一个常见的术语,用于描述指向无效内存地址的指针。这种指针可能是因为指向的内存已经被释放或未初始化,但指针本身却保留了之前指向内存地址的值。

野指针通常是由编程错误引起的,如果程序尝试访问一个野指针所指向的内存,可能会导致程序崩溃或产生未定义的行为。

在C语言中,避免野指针的最佳方式是在定义指针时立即将其初始化为NULL,并在不再需要指针时将其设置为NULL或重新分配内存,这样可以确保指针不会继续指向一个无效的地址。

以下是一些典型导致野指针问题的情况:

没有正确初始化指针:在定义指针后,未将其初始化为有效地址,导致它成为了野指针。

int *ptr; // 未初始化的指针
*ptr = 10; // 尝试给未初始化的指针赋值

释放内存后未将指针置空:在释放了指针所指向的内存后,未将指针本身置为NULL,导致它成为了野指针。

int *ptr = (int*)malloc(sizeof(int)); // 分配内存
free(ptr); // 释放内存
*ptr = 20; // 尝试访问已经释放的内存

返回局部变量的指针:当函数返回一个指向局部变量的指针时,这个指针在函数返回后将会变成野指针,因为局部变量的内存会被释放。

int *getLocalPointer() 
{
    int a = 5;
    return &a; // 返回了一个指向局部变量的指针
}

int main() 
{
    int *ptr = getLocalPointer(); // 获取一个指向局部变量的指针
    *ptr = 10; // 尝试访问已经释放的内存
    return 0;
}

指针越界访问:指针在访问内存时超出了合法的范围,即指针指向的内存区域之外。

#include <stdio.h>

int main() 
{
    int numbers[] = {1, 2, 3, 4, 5};
    int *ptr = numbers;

    // 指针越界访问
    for (int i = 0; i <= 5; i++) 
    {
        printf("%d\n", *ptr);
        ptr++;
    }

    return 0;
}

避免野指针问题对于编写安全的和健壮的程序至关重要。当出现野指针问题时,调试和排查可能会非常困难,因此尽量避免引入野指针问题是十分重要的。

更多C语言相关练习请访问:test_c: C语言练习,包括常见语法练习以及小项目练习。 (gitee.com)

初识C语言系列-5-完结篇-#define,指针,结构体 目录1、前言2、#define定义常量和宏#define定义常量#define定义的宏3、指针内存指针变量的大小??4、结构体终于到了初识C语言的完结篇了,这里再次祝大家五一节日快乐哈!!这个系列结束后我们将正式开始C语言的学习——初阶C语言。博主尽量及时更新,让大家可以学到更多的东西,也感谢大家的多多支持哈!!!前几天博主没有更新,有些小伙伴来催更了,感谢大家伙对我写的博客的喜爱和支持,我会更加努力的!!!有什么问题也劳烦大家可以指出,不理解的地方也要在评论区多多留言哦!最后希望大家多多支持和关注哦!那么 阅读详情

相关推荐

为什么我的Win11家庭版找不到BitLocker?教你两种强制关闭加密的隐藏方法

本文解释了Win11家庭版为何缺少BitLocker功能,并提供了两种强制关闭加密的隐藏方法。通过注册表修改和PowerShell命令,用户可以调出隐藏的加密控制面板或直接操控加密引擎,解决家庭版设备加密的管理难题。

weixin_42535703的博客 1760

第十章编程练习(数组和指针)

排序算法使用常用的冒泡排序法,即判断相邻元素的大小关系,并对需要排序的两个元素交换位置,内层循环一次能保证一个元素调整到合适的位置,在n-1次外层循环中保证所有元素都换到正确的位置。难点在于第三个函数需要传递源数组的首末指针位置,才能正确判断数组长度,因此需要使用首末指针比较的方式来进行循环的条件判断。思路:函数在遍历、比较数组时,同时需要保存元素数值和下标,元素值用于下一次比较,下标值需要保存并在函数末尾返回。ptr+year代表第year年的那个数组的地址,也就是year年第一个月的地址,

m0_74023835的博客 143

Isaac Sim 车辆动力学:从参数调优到户外仿真的挑战与实战

本文深入探讨了Isaac Sim在车辆动力学仿真中的应用,从参数调优到户外场景模拟的实战经验。详细解析了悬架系统、轮胎物理模型等核心参数的设置技巧,并分享了应对户外仿真挑战的实用方案。通过Vehicle Wizard高级使用和传感器配置,帮助开发者高效完成车辆仿真与算法开发。

weixin_29192211的博客 404

如何避免指针操作中的越界错误?

对于数组,在使用指针遍历或者访问元素时,一定要明确数组的大小。访问数组元素时,指针索引( p - arr )应该在0到9之间,即 0 <= (p - arr) < 10。- 对于字符串(C风格字符串是以'\0'结尾的字符数组),在遍历过程中,要确保指针在遇到'\0'之前停止,防止超出字符串实际存储范围。- 如果是使用指针算术运算,如 p = p + n ( n 为偏移量),在运算后需要检查 p 是否仍在合法的内存区域内。这样,在调用函数时,就可以根据实际的数组大小来控制复制过程,避免越界。

2401_88186301的博客 521

脑电分析:为什么大脑信号会“变同步”?——事件相关同步化与去同步化 (ERS/ERD) 全景解析

脑电分析中的事件相关同步化(ERS)和去同步化(ERD)是研究大脑动态节律的重要方法,反映特定任务下脑电频段能量的变化。ERD表示神经元活动分散(功率下降),提示脑区活跃处理信息;ERS则反映神经元同步(功率增强),常与静息状态相关。本文详解了ERS/ERD的生理机制、计算流程(包括基线校正和功率谱分析),并提供了Python实现示例,展示如何通过Welch法和STFT进行时频分析,生成ERD/ERS热力图。该技术广泛应用于运动想象脑机接口、癫痫检测等领域,为理解大脑功能状态提供了量化工具。

qq_32516809的博客 1394

SAP数据导入工具(LSMW) 超级详细教程(批量导入内部订单)

用户提了个需求,让我批量导入内部订单几百个内部订单。我本打算用写段ABAP 代码来调用 BAPI (BAPI_INTERNALORDER_CREATE)就可以了。但想到我很久没有用过LSMW 了,都快要忘记了。于是我采用LSMW的方式,完成了任务。并把过程记录下来,形成教程方便我以后回头查看,分享出来也希望对大家有帮助。

IT小职员 2万+

【C语言】初识指针

【C语言】初识指针

m0_68662723的博客 2862

基于STM32设计的智能水母投喂器(华为云IOT)_170

本项目利用STM32单片机控制各种传感器和水泵等设备,能够自动检测和调整水温和水质等参数,自动换水,自动供氧等等,充分满足了水母的养殖要求和需要。同时,根据水母喜欢的光环境,添加了RGB氛围灯,以及可以手动控制的喂食器等功能,提升了水母养殖的便利性和趣味性。

8806

C语言之初识指针

c语言中指针的初步认识.详细介绍

@初阶牛的博客 1936

Playwright实战:打造绕过全维度前端反爬的无头浏览器爬虫(2026实战版)

Playwright绕过前端反爬的核心是模拟真实:真实的设备指纹、真实的行为轨迹、真实的网络请求;2025年前端反爬的核心检测维度是设备指纹+行为轨迹+网络请求,三者缺一不可;实战中需重点关注WebGL/Canvas指纹模拟、行为随机性、请求头完整性,这是绕过反爬的关键;性能优化需以“不触发反爬”为前提,优先选择浏览器复用、资源拦截,而非无限制并发。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 2094

YOLOv8改进 | 主干网络 | 增加网络结构增强小目标检测能力【独家创新——附结构图】

YOLOv8改进,小目标检测,yolov8

kay_545 6019

C语言指针初识

指针本质上是一种特殊的变量,与普通变量存储数据值不同,指针变量存储的是内存地址。可以把指针想象成是记录某个物品在仓库中位置编号(内存地址)的小纸条。比如,我们有一个整型变量num,指针变量可以存储num在内存中的地址,通过这个地址,我们就能间接访问和操作num。指针为我们提供了一种间接访问数据的方式,这在许多编程场景中都发挥着关键作用。在C语言中,定义指针变量需要指定它所指向的数据类型。数据类型 *指针变量名;int *ptr;// 定义一个指向整型数据的指针变量ptr这里的是指针声明符,它表明ptr。

jieyucx的博客 1189

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【C语言】—— 指针一 : 初识指针(上)

(中央处理器)在处理数据的时候,需要的数据是从内存中读取的,处理后的数据也会放在内存中。函数来求字符串长度,代码逻辑是:传入字符串首元素的地址(指针),然后找到字符串最后一个元素的地址(指针),两个指针相减,得到的是中间的元素格式,即整个字符串的长度啦。取出变量的地址,把他放在哪呢?因此,对于数组来说,我们只要找到了他的首元素地址,那他剩下元素的地址也能顺藤摸瓜找到。好啦,本期关于指针就介绍到这里啦,希望本期博客能对你有所帮助,同时,如果有错误的地方请多多指正,让我们在C语言的学习路上一起进步!

yusjushd的博客 1363

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C语言 初识指针

c语言指针

2302_81328814的博客 2055

C语言、初识指针

这篇文章系统讲解了C语言指针的核心概念和使用方法。主要内容包括:1)内存和地址的关系,用公寓房间比喻内存单元;2)取地址操作符(&)获取变量地址;3)指针变量的定义和使用,以及解引用操作符(*)的作用;4)指针变量的类型和大小在不同平台下的差异;5)指针运算,包括加减整数和指针相减;6)二级指针的概念和使用;7)指针的分类(指针数组、数组指针等)。通过生活化的比喻和代码示例,帮助读者理解指针这一复杂但重要的编程概念

加油,量变引起质变 2126

初识C语言·指针(1)

总结一下,const在*前面,修饰的是*pa,会导致a的值无法被改变,也即是指针变量指向的元素的值为定值,const在*后面,修饰的是pa,会导致pa存的地址无法被改变,也就是指针变量无法被修改。这里的p就是一个指针变量,因为a是整型类型的,所以p是int* ,同理,如果a是char类型的,p的类型就是char*,那按道理来说,p存了a的地址,打印出来的结果应该是一样的,来试试。是的,它也代表取地址,不然你看,我们使用scanf的时候,为什么加这个,就是为了取地址出来,然后把“外卖”送进去咯。

更新各种计算机技能~ 1370

初识C语言指针

本文摘要: 指针是C/C++等语言中的重要概念,直接操作内存地址。文章系统讲解了指针的核心知识:1) 指针变量存储地址,大小由机器架构决定;2) 指针类型决定运算步长(如int*+1跳4字节);3) 避免野指针需初始化或置NULL;4) const修饰指针的两种用法;5) 指针运算包括加减、关系比较等;6) 传址调用实现变量交换;7) 二级指针存储指针变量的地址;8) 指针数组模拟二维数组;9) 字符指针处理字符串;10) 数组指针和函数指针的特殊用法。通过代码示例演示了指针操作原理及常见应用场景。

2301_80135020的博客 1033

C语言初识指针

初始指针笔记总结

ltzoro的博客 706

【C语言】深入理解数组和指针——初识指针

哈喽大家好,我是保护小周ღ,C语言,接下来给大家带来的是深入理解数组和指针的初识指针,这篇主要讲的是基础指针的相关知识,是博主的所见所闻,细节上的知识后面会这里面没有提,会放在后期的文章中与数组相结合讲,多多包含~

保护小周ღ的博客 2823

c语言---9 初识宏、指针

define是一个预处理指令,有两种用法,一种是用define定义常量;另外一种是define定义宏。 下面的例子为利用define定义常量 运行结果为1000. 下面的例子是define定义宏 运行结果为5. 将改为,则运行结果为11.预期的运行结果为4x5=20,为什么会出现这样的结果呢?因为define定义宏是替换,就变成了4x2+3=11了,4x2为X,Y仍然是3。如何让其得到正确的结果20呢?在写宏的时候,将X与Y括起来,因为X与Y可能不是简单的数字,它可能是表达式,所以定义宏的时候应该是这样的定

qq_42822743的博客 382
上一篇: 扫雷游戏(C语言)
下一篇: assert的使用
Jett_Lin
博客等级 码龄5年 305粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值