首页 > 其他分享 >c语言-指针

c语言-指针

时间:2024-07-28 11:25:04浏览次数:8  
标签:语言 -- ++ 地址 num 数组 指针

6 指针

一、指针是什么

1、指针是地址


(1)地址是什么?
a. 内存中用于cpu标识的一组编号   -- 是以十六进制的形式存储的
b. cpu 要么是32位,要么是64位的地址针

alt text

注:这里电脑是64位,而空间是16G,这是因为电脑还有内存条,一个内存条有8G,所以总共是16G。这里的RAM是动态内存,是正在使用的内存,如果关闭正在使用的内存,那么动态内存就会被释放。

c. 32位,地址是4字节,--4G        64位,地址是8字节,   --8G

alt text


(2)为什么要用指针?
a. 数据传递时,容易出现值传递

alt text

输出a的值依旧是10
b. 嵌入式是底层程序,操作内容也是以地址的形式进行操作
c. 地址如何操作?
-- 程序没有能力直接操作内存地址      --c语言提供一种数据类型来操作地址 -- 指针


2、指针是一种数据类型,保存地址的数据类型


二、指针的意义

3、-- 保存变量空间的地址

alt text

三、指针的表现形式

4、指针类型: 类型 *

四、指针的空间大小?

5、-- 固定8字节

指针里面只保存地址,空间大小与类型无关,固定8字节   -- 因为电脑是64位
指针类型: "类型 *"

alt text

五、指针的运用

6、指针变量

(1)定义

a. 类型 *标识符 = 初始值

注:这里因为是指针类型,所以类型是类型 *,所以指针类型的变量就是类型 *标识符 = 初始值。如果是数组类型就是类型 标识符[长度],所以数组类型的变量就是类型 标识符[长度] = 初始值。

b. 标识符 组成:数字、字符、下划线
-- 不能是数字开头,不能是关键字,区分大小写,有意义

c. 初始值
-- 无初始化 -int *p --随机地址 --野地址 --避免使用,因为可能更改重要的地址
-- 指定地址初始化 --int num = 10; int *p = &num --&取地址符,此时p中存放的是num空间的地址。
-- 指定空地址 -- int *p = NULL; --空指针; NULL -- 空地址-nil -》只读的地址。 --推荐使用


(2)应用

A. 给指针变量赋值 -- &取地址符
-- int num = 10; int *p = &num --此时p中存放的是num空间的地址。

B. 通过指针变量操作地址空间    -- * --  解空间

-- *的用法:
- * -- 乘法 -- a * b
- * -- 指针类型 -- int *p= NULL;
- * -- 解地址 -- *p           -- 解p中存放的地址,得到地址空间的内容.

-- 赋值:*p = 10;           -- *p表示指针变量中地址所指向的空间

-- 取值:int b = *p; -- *p表示指针变量中地址所指向空间的值

-- *p等同于变量名num

alt text

C. 一个指针指向多个地址空间 --指针是变量

alt text

alt text

alt text

注:const 修饰的是* p,那么* p的值不能改变,就是值不能改变,而p可以改变,也就是地址可以改变。

D. 多个指针指向一个地址空间
--  其中一个指针改变该地址的值,另一个指针获取时也会改变

alt text

alt text


E. 指针偏移 --指针运算(重点)

注:首先,所有的常量都来自常量区,int num = 1;就是把常量区的值赋值到栈区,而栈区开辟空间默认是连续的,也就是说 int num1 =10;int num2=10;中num1和num2这两个空间的地址是连续的,所以地址偏移后,就是相邻的地址。

1)指针偏移一位,物理地址偏移一个数据类型的空间大小

alt text

-- p+1 --指针偏移一位 --因为指针p是int类型,int类型的空间大小是4字节,所以p的地址+4

alt text

-- (long)p 强转long整型数据

2)* p++ -- ++*p -- *++p的区别

首先, * 和++运算符的优先级是相同的,而且是从右往左的执行顺序。例如 * p++,是先执行++运算符,这里的++运算符是指p的运算,这里的p++是先运行后++,也就是先把p给前面的运算符使用,先解地址得到值,并执行printf,而p的值也会改变,会在原来的编号后面加4字节,这里的编号不是真正的物理地址,相当于一个寄存器对物理地址的编号,一位是一个字节,所以直接加4

-- ++ * p,按照从右往左执行的顺序,先解地址得到值,后++,而++*p的特点是先++后赋值,这里的++运算符是指 * p的运算,所以 * p+1是11.

-- * ++p,按照从右往左执行的顺序,先++后解地址,而这里的++是++p,是对p先++后运行,所以P的地址+1后,再解地址得到20

alt text

3)指针与一维数组

tip:地址偏移:需要满足地址连续和是同样的数据类型,这两种条件都满足的数据类型是数组。所以这里将指针和数组放在一起研究。

-- 数组名代表数组的首地址 - 首个元素的地址

alt text

alt text

-- 使用数组名代替指针变量操作数组元素 -- 指针偏移

alt text

注:不能使用数组名++的形式,进行地址偏移 例如int num[10];-- num是数组的首地址,num++是错误的,因为num++有赋值特性,将首地址改变了,所以数组名用不了++。

-- 使用指针变量代替数组名操作数组元素 --数组名[下标]

alt text

int *p = num; p存放了num的首地址,所以p[0]就是num[0],p[1]就是num[1]

注:p[i] --元素空间 --[] 可以理解为解地址 --scanf("%d",&p[i]) --scanf("%d",p+i);

4)指针与字符数组

-- char ch[1024] = "hello";
char *p = ch;  => char *p = "hello";

注:这里char *p= "hello";p存的是首个元素的地址,“hello”是常量,p的地址是常量区中存放“hello”的首地址,常量区的值是不可以被改变的,例如 * p = ‘H’; 是错误的。

5)数组指针与指针数组

a. 数组指针  -是一个指针 -是一个数组类型的指针 -指向数组中的指针

--数组指针定义: 类型 (*标识符)[长度];
这里必须要加(),如果不加,先读的就是类型 *,就是指针类型了。

alt text

alt text

注:num是数组名,他只是指向首个元素的地址,而&num就是指向整个数组的地址,p1+1是加了一整个数组的空间大小。

b. 指针数组   --是一个数组 --指针类型的数组 --存放的是数组元素的地址

alt text

注:p[0]存的是地址,地址都是8字节的。 --p存的是首个元素的地址,而这个元素也是地址,所以**q = P+2,q指向的是“rose”的地址。

c. p[0] --代表指针数组中第一个元素的值 --地址 --空间大小: 8

d. p --代表数组名 --首个元素的地址,首个元素是地址 --p的类型是地址的地址 --是个二级地址 --char **表示

6)指针与二维数组

注:二维数组相当于一维数组类型的一维数组,元素是一维数组

alt text

alt text

alt text

注:a是数组名,是a[3]数组的首个元素的地址,而&a是整个数组的地址,相当于数组类型的数组指针int (*c)[3]。 c[0] = a,c代表是首行元素的地址,上面说到[]有解地址的作用,这里c[]就代表是单个元素的地址,c[0]就是数组的首个元素的地址, c[0][0]是首个元素,而&[0][0]是首个元素的地址。

a. 如何获取二维数组的元素 --四种方式

-- 纯数组形式 - num[i][j]

-- 纯指针形式 - *( * (num+i)+j)

tip:
num --首行元素的地址
num+i --第i行元素的地址
*(num+i) --第i行首个元素的地址
*(num+i)+j --第i行第j个元素的地址
*( * (num+i)+j) --第i行第j个元素的值

-- 行数组列指针 --*(num[i]+j)

tip:
num --首行元素的地址
num[i] --第i行元素的地址
num[i]+j --第i行第j个元素的地址
*(num[i]+j) --第i行第j个元素的值

-- 行指针列数组 --(*(num+i))[j]

tip:
num --首行元素的地址
num+i --第i行元素的地址
*(num+i) --第i行首个元素的地址
( * (num+i))[j] --第i行第j个元素的值

理解 tip:int num[i][j] = {a,b};  a和b分别是一维数组,而由于int a[]={};   int b[]={};  ,所以a和b分别代表数组首元素的地址,num[0]=a,num[1]=b,这是行数组的形式。如果行是指针的话,那么num代表着数组首元素的地址,也就是a的地址,num+1就是b的地址,*num就是a,*(num+1)就是b,也就是b的首元素的地址。记住指针存的是地址,而[]有解地址的作用。

7)多级指针

alt text

tip:p指向变量的地址(存放),*q指向一级指针的地址(存放),**w指向二级指针的地址。每一个变量生成后都有地址,包括指针。

标签:语言,--,++,地址,num,数组,指针
From: https://blog.csdn.net/m0_71813740/article/details/140724846

相关文章

  • c语言模拟Python的命名参数
    最近在书里看到的,让c语言去模拟其他语言里有的命名函数参数。觉得比较有意思所以记录一下。目标众所周知c语言里是没有命名函数参数这种东西的,形式参数虽然有自己的名字,但传递的时候并不能通过这个名字来指定参数的值。而支持命名参数的语言,比如python里,我们能让代码达到这种效......
  • C++字体库开发之go语言绑定六
    export.h#defineFONTVIEW_API__declspec(dllimport)typedefvoid*GoFontSetPtr;#ifdef__cplusplusextern"C"{#endifFONTVIEW_APIGoFontSetPtropenFontSet(constchar*stream,size_tsize);FONTVIEW_APIvoidfreeFontSet(GoFontSetPtrfontset);......
  • C语言内存函数精讲
    目录引言1.内存分配函数malloc2.内存释放函数free3.内存拷贝函数memcpy4.内存移动函数memmove5.内存设置函数memset6.内存比较函数memcmp总结 引言在C语言编程中,内存管理是核心技能之一。C语言提供了一系列内存操作函数,这些函数在动态内存分配、数据拷贝和比较等方......
  • 在当前的数字化时代,Cobol 语言如何与新兴技术(如云计算、大数据、人工智能)进行融合和交
    Cobol语言作为一种古老的编程语言,与新兴技术的融合和交互需要一些额外的工作和技术支持。以下是一些将Cobol与新兴技术结合的方法:云计算:Cobol程序可以迁移到云平台上运行,通过云提供的弹性和可扩展性,为Cobol应用程序提供更高的可用性和可伸缩性。此外,云服务提供商也提供了......
  • 【C语言】结构体
    目录一、结构体概念二、定义结构体类型三、定义和引用结构体类型变量3.1 先定义结构体类型再定义变量名3.2 在定义类型的同时定义变量3.3直接定义结构类型变量3.4类型与变量区别   3.5结构体的嵌套定义   3.6结构体类型变量的引用3.7 结构体类型......
  • C语言——字符串拼接strcat及自实现代码
    strcat函数在C语言中,strcat函数用于将两个字符串连接起来,即将源字符串(sourcestring)追加到目标字符串(destinationstring)的末尾,并返回目标字符串。这个函数定义在头文件<string.h>中。函数原型如下:char*strcat(char*dest,constchar*src);dest:目标字符串的指针,这个字符......
  • 数据结构——链式二叉树(C语言版)
    链式二叉树的结构⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址。                                ......
  • 编程语言之泛型困境
    困境泛型不可能三角泛型困境的本质是,关于泛型,你想要缓慢的程序员、缓慢的编译器和臃肿的二进制文件,还是缓慢的执行时间。简单来说就是:要么苦了程序员,要么苦了编绎器,要么降低运行时效率。不同语言对泛型的考量以C、C++和Java为例,它们在泛型的设计上有着不同考量:C语言:是系统......
  • 三种语言实现二分(C++/Python/Java)
    题目给定一个按照升序排列的长度为......
  • 学习c语言第十五天(初阶测评)
    选择题1.下列程序输出结果为672.下列程序输出结果为 死循环打印3.i和j的值分别为什么 214.k的终值是什么905.输出结果是什么 16.正确的是    C7.C语言规定main函数位置    C8.不正确的是    D9.正确的是     c ......