当前位置: 首页 > article >正文

C和指针:指针

内存和地址

程序视角看内存是一个大的字节数组,每个字节包含8个位,可以存储无符号值0至255,或有符号值-128至127。

多个字节可以合成一个字,许多机器以字为单位存储整数,每个字一般由2个或4个字节组成。

由于它们包含了更多的位,每个字可以容纳的无符号整数的范围是从0至4294967295(2^32-1)。尽管一个字包含了4个字节,它仍然只有一个地址。

它的地址是最左边字节或者最右边字节的位置,不同的机器有不同的规定。另一个需要注意的是边界对齐(alignment)。要求边界对齐的机器上,整型值存储的起始位置只能是特定的字节,通常是2或4的倍数。

内存中的每个位置由一个独一无二的地址标识。

内存中的每个位置都包含一个值。

如果知道一个值的存储地址,可以根据地址取得这个值。但是地址不好记,所以可以通过变量名访问地址的值。

名字与内存位置之间的关联并不是硬件所提供的,是由编译器实现的。

int a = 112,b = -1;
float C = 3.14;
int *d = &a;
float *e = &C;
值和类型

c声明为浮点数,但是存放在内存中使用的整数,它们可以被解释为整数,也可以被解释为浮点数,取决于它们被使用的方式。如果使用的是整型算术指令,这个值就被解释为整数,如果使用的是浮点型指令就是浮点数。

不能检查一个值的位来判断类型。为了判断值的类型,必须观察程序中这个值的使用方式。

指针变量的内容

指针变量存放指针指向变量的地址。

d和e的内容是地址而不是整型或浮点型数值。d的内容与a的存储地址一致,而e的内容与c的存储地址一致,

间接访问操作符

通过一个指针访问指向的地址的值间接访问或解引用指针,间接访问的操作符*。

*d=112

*e=3.14

*&a = 25;

把值25赋值给变量 a。

&产生变量 a的地址,它是一个指针常量。*操作符访问其操作数所表示的地址。表达式中操作数是a的地址,所以值25就存储于 a中。

*(int *)100= 25

强制类型转换把值100从“整型”转换为“指向整型的指针",对它进行间接访问。如果 a存储于位置100,那么这条语句就把值25存储于a。

需要通过地址访问内存中某个特定的位置,它并不是用于访问某个变量,而是访问硬件本身。

未初始化和非法的指针

下面的指针a没有初始化就进行赋值,是非法的。a存放的是一个随机的整数,行为未定义。

int*a;
*a = 12;
NULL指针

NULL指针是一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为NULL,可以给它赋一个零值。为了测试一个指针变量是否为NULL,你可以将它与零值进行比较(源代码约定)。

NULL指针并未指向任何东西,因此对NULL指针进行解引用操作是非法的。在对指针进行解引用操作之前,首先必须确保它并非NULL指针。

指针的指针

int a=12;int *b=&a;int **c=&b;

c的类型是一个指针,b是指向整型的指针,c是一个指向整型指针的指针。

指针表达式

char ch= ’a’;char *cp=&ch;

?为ch后面的内存位置(方便后续使用)。

ch

作为右值使用表示表达式的值为'a'

作为左值使用表示内存的地址而不是该地址所包含的值。

&ch

作为右值表示变量ch的地址,这个值等于变量cp存储的值。

只能作为右值,不能作为左值。

cp:右值是cp的值(存放ch的地址),左值是cp所处的位置(左值一般是等号左面用作赋值)。

&cp:右值表示取指针变量的地址,指向字符指针的指针。左值非法。

*cp:右值表示间接访问ch‘a’。左值表示ch的地址

*cp+1

右值:*优先级高于+,所以执行间接访问操作,得到值‘a’,+1后得到’b’。

左值:非法

*(cp+1)

右值表示?的值。左值表示?的地址

++cp

右值:表达式的结果是增值后的指针的一份拷贝。执行后cp指向?

左值非法

cp++

右值:增加cp的值,执行后cp指向?。但先返回cp值的一份拷贝再增加cp的值。表达式的值式cp原来值的一份拷贝。左值非法。

*++cp

右值:间接访问操作符作用再增值后的指针的拷贝上,表示?的值。

左值:表示?内存地址。

*cp++

右值和左值分别是变量ch的值和ch的内存位置。cp指向?

后缀++操作符的优先级高于*操作符。

(1)++操作符产生cp的一份拷贝.

(2)++操作符增加 cp的值.

(3)在cp的拷贝上执行间接访问操作.

++ *cp

右值表示ch变为b,左值非法

(*cp)++

与12类似,结果是ch增值前的值(‘a’),但是ch的值变为’b’。

++*++cp

*++cp,需要做的只是增加它的结果值。

指针运算

当一个指针和一个整数量执行算术运算时,整数在执行加法运算前始终会根据合适的大小进行调整。合适的大小就是指针所指向类型的大小,调整就是把整数值和合适的大小相乘。

算术运算

(1)指针士 整数

指向数组中某个元素的指针

#define N_VALUES 5
float values[N_VALUES]; 
float *vp;
for( vp = &values[0]; vp< &values[N_VALUES];)
*vp++ = 0;

for语句的初始部分把 vp指向数组的第1个元素。

经过第1次循环之后

经过5次循环之后,vp就指向数组最后一个元素后面的那个内存位置。

(2)指针 一 指针

只有当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针,两个指针相减的结果的类型是 ptrdiff_t,它是一种有符号整数类型。减法运算的值是两个指针在内存中的距离(以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。

关系运算

指针都指向同一个数组中的元素可以进行关系运算,判断哪个指针在数组的前面或后面。


http://www.kler.cn/news/302412.html

相关文章:

  • 超越博士水平:OpenAI o1模型在科学和编程领域的卓越表现
  • 【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)
  • SpringBoot学习(11)MongoDB使用
  • 栈和队列的算法题目(C语言)
  • 8月更新速递丨秋风送爽,EasyTwin产品能力升级不停~
  • 叉车智能ai防撞系统解决方案
  • TS 常用类型
  • 小程序的右侧抽屉开关动画手写效果
  • Linux网络服务只iptables防火墙工具
  • 网络编程day04(UDP、Linux IO 模型)
  • Hive SQL基础语法及查询实践
  • Linux网络:网络套接字-TCP回显服务器——多进程/线程池(生产者消费者模型)
  • “区块链积分系统:支付安全与效率的新篇章
  • 内外网文件安全交换如何做到?
  • 春日美食汇:基于SpringBoot的订餐平台
  • windows vscode ssh 连接远程服务器
  • 工厂模式(二):工厂方法模式
  • 使用Python或者GO实现OTP令牌的获取
  • <Linux> 基础IO
  • 利用物化视图刷新同步表记录
  • 从概念到现实,国际数字影像产业园如何打造数字文创产业标杆?
  • Android 开发避坑经验(2):深入理解Fragment与Activity交互
  • 宽哥之家小程序任务脚本
  • 服务器深度解析:五大关键问题一网打尽
  • CentOS 7 上安装 Docker
  • 【Three.js】实现护罩(防御罩、金钟罩、护盾)效果
  • 【PGCCC】PostgreSQL重做日志内幕!如何掌握事务日志记录的“黑魔法”
  • 9月13日星期五今日早报简报微语报早读
  • ssm“健康早知道”微信小程序 LW PPT源码调试讲解
  • P1544 三倍经验 (记忆化搜索)