【C语言】指针的理论详解-创新互联

指针!!!

成都创新互联公司长期为上千多家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为阳明企业提供专业的成都网站建设、网站制作,阳明网站改版等技术服务。拥有十多年丰富建站经验和众多成功案例,为您定制开发。

目录

指针!!!

指针简介

计算机的存储机制

定义指针

指针的操作

& 取地址

* 取内容

数组与指针

逐一打印数组元素

数组就是指针

数组名就是指针变量

注意事项

错误示范:

1.定义了指针不赋初值,直接引用指针变量

2.同级指针之间才能相互赋值


本篇博客为C语言学习笔记,学习视频链接:

[C语言] 指针的详解与应用-理论结合实践,真正理解指针!


指针简介
  • 指针(pointer)是C语言的一个重要知识点,其使用灵活,功能强大,是C语言的灵魂。
  • 指针?什么是指针?从根本上看,指针是是一个值为内存地址的变量(或数据对象)。指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问。
计算机的存储机制

指针和内存是离不开的,先了解一下内存是怎么定义的。

  • 内存的框图如上,计算机通常把内存分配成上图模式的线性空间
  • 内存分为一个个线性的区域,每个线性区域,都是一个字节为单位的,线性分配下去
  • 每个字节都对应一个地址(独一无二的地址)

int a = 0x12345678;     //0x是十六进制前缀,后面是实际的数据

short b = 0x5A6B;

char c[] = {0x33,0x34,0x35};

在计算机系统里,int类型变量,代表4个字节数据,4*8 = 32个二进制数来表示,就是32位,但是要注意在51单片机里,int类型是16位的。

int a = 0x12345678;  这样定义一个int类型的变量,变量名称为a,把它分开成四个字节来看
0x12 | 34 | 56 | 78 
如上图内存的分配可以看到,0x78存储在0x4000地址,0x56存储在0x4001地址,0x34存储在0x4002地址,0x12存储在0x4003地址,总共占用四个字节。
数据的小端(低位)存储在内存地址的低位,就是把小端存在前面,这种分配方式叫小端模式。

另一种存储模式叫大端模式:数据的大端(高位)存储在地址的低位。

现在的计算机普遍运用小端模式分配地址。

short类型的变量当然也是小端模式存储。

char类型的数组,就是按照顺序存储,对照上图。数组在内存中分配的是连续的内存空间。

那如果是short类型的数组呢?

举个例子,short d[] = {0x5A6B, 0X7C8D};

那么存储方式应该是先给数组开辟一段连续的地址,然后按照数组的顺序依次分配地址,数组内地每一个数据都是小端模式 :第0位放在地址低位……

地址              内存

0x4009        0x6B

0x400A        0x5A

0x400B        0x8D

0x400C        0x7C


定义指针
  • 指针即指针变量,用于存放其他数据单元(变量/数组/结构体/函数等)的首地址。若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针。
  • 定义一个指针变量:

指针变量的x字节,起码要存的下这个数据,所以不同系统,指针的位宽用不同的长度

用示例演示一下

可以看到我定义的指针位宽是4个字节,我猜是因为vscode调用 gcc编译器是32位的,所以指针p位宽是4,在Dev-C++里运行,针p位宽是8


指针的操作
  • 若已定义:
         int a;        //定义一个int型的数据           
    int *p;        //定义一个指向int型数据的指针
  • 则对指针p有如下操作方式:

& 取地址
  • 如果&运算符左右都有变量,那么这个符号就代表位运算&;
  • 如果&运算符只有右边是变量,那个就代表取地址的意思
* 取内容
  • 如果*运算符左右都有变量,那么这个符号就代表乘法运算符;
  • int *中的*只是一个标识,一个代号
  • 如果* 只有后面有变量,而前面没有数据类型,那就是取内容,就是解引用的意思

此时想到狄泰软件学院唐老师说的:“编译运行试试就知道了呗,反正电脑又不会爆炸 !”

用示例说话~

运行结果的第一行是打印a这个变量
第二行是取出a的地址
第三行是取出指针变量p指向德内容a (p取了a的地址,代表p指向a,引用p,就是引用a)(地址间接访问数据)

指针变量的运算一般只有“+”和“-”,没有“”或“/”或乘方开方等等,因为它只是个地址

由p++运算 可以看到,p的地址加了一个char类型的数据宽度1,如果改为int类型的变量会怎么样呢?                

可以看到地址加了4(int型变量的数据宽度就是4)

因为指针越界了,指向了非法的位置,出现了不可预知的错误,所以我才给注释掉~~~

指针的++或--一般用在数组里边,对于这种单独的变量就是做一个演示。


数组与指针

数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。数组的定义等效于 申请内存、定义指针和初始化

例如:        char c[] = {0x33, 0x34, 0x35};
等效于:     申请内存
  定义char *c = 0x4000;
  初始化数组数据

利用下标引用数据也等效于指针取内容

c[0];        等效于:*c;
c[1];        等效于:*c+1;
c[2];        等效于:*c+2;

逐一打印数组元素

之前是习惯了用for循环打印数组

现在就可以用指针了

定义一个指针变量p,变量p++就相当于数组下标加加

数组取下标就是指针取内容的另一种表示形态

数组a本身就是一个指针

如果将数组类型转换为int类型,效果也是一样的~
因为int类型的变量占4个字节,所以指针每次加1,都会跳4格,但是实际访问数据就是依次访问的(根据变量类型宽度而定)

上文提到了申请数组的等效方法:

  1. 申请内存
  2. 定义char *c = 0x4000;
  3. 初始化数组数据

申请内存需要用到 #include头文件

malloc(3*4);    //申请内存 3个变量*4个字节 返回值是void*
 //void*是空*   void*可以表示任何类型的指针

定义指针        int *a;

a = malloc(3 * 4);        //定义

然后初始化数据

*a = 0x38;
 *(a + 1) = 0x32;
 *(a + 2) = 0x35;

这种申请内存的方法,还是第一次接触呢~

数组就是指针 数组名就是指针变量
注意事项
  • 在对指针取内容之前,一定要确保指针指在了合法的地址,否则将会导致程序出现不可预知的错误
  • 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告

数组是有越界的,数组越界和指针指向了非法位置是一样的性质 

因为数组就是指针,那指针也可以越界的说法

错误示范: 1.定义了指针不赋初值,直接引用指针变量

举个栗子

只有定义但是没有赋初值,运行出错了

0x55是随意赋的地址,地址是非法的,所以运行不出来

赋初值就可以运行了

2.同级指针之间才能相互赋值

变量看做零级指针

普通的指针就看做一级指针

指针再取地址就是二级指针

指针级别不同造成的错误:

有个警告,从int*类型赋值给int类型,没有进行强制转换

如果是 p = a; 也是不可以的

a = *p;        对p取内容,他们就变成同级指针了,就可以赋值了

p = &a;        对a取地址,也变成同级指针


有关指针的原理,目前就学了这么多!

初级指针

二级指针,函数指针,结构体指针……这些复杂的指针,暂时用不到~_~

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


本文名称:【C语言】指针的理论详解-创新互联
网页网址:http://myzitong.com/article/cedhgi.html