C语言基础——认识C语言(五)

2023-03-30 00:00:00 变量 内存 地址 指针 结构
序文
欢迎阅读  霖海岛LHaisland  原创的C语言合集的第五篇文章,本文字数为3058字,全文阅读需要约10分钟。由于笔者能力有限,如有疏漏或错误的地方,希望读者朋友们不吝斧正,谢谢大家。
上篇文章地址:C语言基础——认识C语言(四)

本文我们将简单介绍指针结构体

十三、指针

1.地址

(1)生活中的地址

(2)内存地址

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。所以为了有效使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地 址

变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。

下面如图所示:

比如说这段代码int num =10;可以理解成为我们向内存申请4个字节(int)的空间来存放数值10,然后我们取出num的地址,因为num的大小是4个字节,每一个字节都有自己的地址,我们取出来的地址是个字节的地址(较小的地址),然后以%p(以地址的形式打印)形式打印。这里我们对这段代码进行调试,启用内存窗口查看num的地址,得到了0x009dfbb8,这是num的地址。

它内存中的数据为0a 00 00 00,这又是什么意思呢?

十进制是用 0~9 十个数字来组成,八进制是由 0~7 八个数字组成,16进制由 0~9 a b c d e f 组成,其中a表示10,b表示11,以此类推f表示15。二进制由0和1组成。

因为4个字节等于32个比特位(bit),所以对于数值10来说,二进制表达方式是这样的:



对于我们刚才看到的0a 00 00 00,只不过他是倒着存放的,至于为什么是倒着存放的,我们在未来的文章中会提到。

所以我们需要明白的事情很简单,就是数值10确确实实的被我们存放进了内存中;而且我们也了解了,%p是用来打印地址的。

那这里笔者引入一个新问题,那我们如何来存放地址呢?

int p = #吗?我们稍后解释。

2.什么是指针

指针(Pointer)是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,在同一CPU构架下,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。——百度百科
在程序中,我们的数据都有其存储的地址。在程序每次的实际运行过程中,变量在物理内存中的存储位置不尽相同。不过,我们仍能够在编程时,通过一定的语句,来取得数据在内存中的地址。地址也是数据。存放地址所用的变量类型有一个特殊的名字,叫做“指针变量”,有时也简称做“指针”。——OI Wiki

指针是编程语言中的一类数据类型及其对象或变量(实体),用来表示或存储一个存储器地址,这个地址值直接指向存在该地址的对象的值。这个对象的值,可能代表另一个变量、结构、对象或函数。在计算机科学中,指针是一种简单形式的引用。指针有两种含义,一是作为数据类型,二是作为实体。前者如字符指针、浮点指针等等;后者如指针对象、指针变量(为对被引用类型的实体的引用)等。——维基百科

计算机系统的内存拥有大量的存储单元,每个存储单元的大小为1字节,为了便于管理,必须为每个存储单元编号,该编号就是存储单元的“地址”,每个存储单元拥有一个的地址。
通过以上的描述以及笔者的理解,指针的特点如下:
  • 指针是是一种数据类型。
  • 指针是内存中小单元的编号,也就是地址。
  • 平时我们所说的指针,通常指的是指针变量,是用来存放内存地址的变量。

所以我们上面留存的问题——如何存放地址?的答案就是指针变量。

比如我们存放之前num的地址可以这么写:

int*  p = #   这里的p就是指针变量。我们来分别分析一下他们都是什么:

int:说明p指向的对象是int(整形)类型的。

*:说明p是指针变量。

p:0x009dfbb8(存放的地址)——指针变量就是用来存放地址的。

C语言基础——认识C语言(四)我们介绍了单目操作符。

*p; 也就是解引用操作符,意思是通过p中存放的地址,找到p所指向的对象,*p就是p指向的对象。
由上面我们可以知道,p存放着num的地址,*p也就指向了num,也可以理解为*p=num。
这里我们举一个简单的例子:

这里我们让num=10,然后通过*p去改变num的值。结果如下:

所以我们确实通过指针寻到了地址进行解引用,然后找到了他所指向的num,把他在内存存储的值改掉了。

所以我们可以比较一下&和*这两个单目操作符,其实他们两个可以说是一对。

&:单目操作符,用来取得其操作对象的地址。

* :单目操作符,与取址运算符&相反,* 用于当已经具有一个指针,代表访问指针所指向的内存空间,因此也被称为解引用操作符。

我们在这里简单总结一下:指针就是地址,指针变量是用来存放地址的。

在一般交流的情况,我们会说p是个指针,实则指的是p是一个指针变量。

3.指针变量的大小

这里的x86代表32位平台,x64代表64位平台。

结论:指针大小在32位平台是4个字节,64位平台是8个字节。

对于指针我们现在了解到这里即可,在未来的章节还会详细的分享。


十四、结构体

C语言提供了基本的数据结构,例如 char 、short 、int 、float....等类型,这些称为内置类型。

程序员可以使用结构体来封装一些属性,设计出新的类型,在C语言中称为结构体类型

结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。

1.定义结构体类型

结构体的格式如下:

struct 结构体名{         类型名1 成员名1;         类型名2 成员名2;         ……         类型名n 成员名n;};

示例:

struct Student    {        char name[20];  //名字        int age;        //年龄        char sex[5];    //性别        char id[15];    //学号    };

2.定义结构体变量

定好好结构体类型之后, 我们就可以利用我们定义的结构体类型来定义结构体变量。

格式: struct 结构体名 结构体变量名;

  • 先定义结构体类型,再定义变量:

 struct Student    {        char name[20];  //名字        int age;        //年龄        char sex[5];    //性别        char id[15];    //学号    };    struct Student stu;
  • 定义结构体类型的同时定义变量:
struct Student    {        char name[20];  //名字        int age;        //年龄        char sex[5];    //性别        char id[15];    //学号    }stu;
  • 匿名结构体定义结构体变量:

struct    {        char name[20];  //名字        int age;        //年龄        char sex[5];    //性别        char id[15];    //学号    }stu;

第三种方法与第二种方法的区别在于,第三种方法中省去了结构体类型名称,而直接给出结构变量,这种结构体大的问题是结构体类型不能复用。笔者更推荐前两种定义方法

3.结构体成员访问
一般对结构体变量的操作是以成员为单位进行的,引用的一般形式为:结构体变量名.成员名。"."为结构成员访问操作符
示例:
struct Student    {char name[20];  //名字int age;        //年龄char sex[5];    //性别char id[15];    //学号    };struct Student stu;stu.age=19;printf("%d",stu.age);//访问student中的age

我们还可以这么操作:

这里我们结合一下刚刚学的指针与函数,我们把stu的地址取出来,传递出去。

可以看到,结果是一样的。但是在12行这么写比较啰嗦。

我们还可以这样去写。

->操作符的使用方法:结构体指针变量->成员名

在未来的自定义类型详解章节中,笔者还会继续对结构体展开讲解,目前我们了解到这里即可。

至此我们已经对C语言有了一个比较全面的初步了解,章认识C语言到这里也就结束了。

下一章节——分支与循环结构,在这一章节中,笔者将依次分享——分支语句(if、case)、循环语句(while、for、do...while)、跳转语句(goto),以及他们相关的详细内容。
如果您在阅读中发现内容错误或者有好的想法以及建议,欢迎在公众号内给我们留言,我将不胜感激!
感谢您能够阅读到这里,我们下次再会!

编辑:  霖海岛LHaisland

审核:            天天写bug

图文来源:  霖海岛LHaisland

相关文章