• 【C语言基础】Chap. 4. 初识指针和结构体


    1. 指针

    了解指针前,首先要明确内存的定义:内存是电脑上重要的存储器,计算机中所有程序的运行都是在内存中进行的。

    所以为了有效地使用内存,大多数现代计算机都把内存分割成一个个小的内存单元

    而为了能够有效地访问到内存的每个单元,计算机又给内存单元进行了编号,以与其他内存单元进行区分,这些编号就被称为该内存单元的地址(address)。

    此时就引出两个问题:

    1. 内存是怎么编号的?

     答:计算机的32位和64位实际上指的是该计算机地址线的根数,它们的通电与否分别代表1和0,这就是把电信号转换成数字信息——二进制序列。以32位为例,其能够产生的如总共有2的32次方个的序列,就可以作为内存单元的编号(地址)。如下:

     
    
    1. 00000000000000000000000000000000
    2. ...
    3. 00000000000000001111111111111111
    4. ...
    5. 11111111111111111111111111111111
    2.一个内存单元是多大空间?

     答:每个内存单元的大小是1个字节,即8个比特。

    在C语言中添加数据(如变量)时,会给对象分配空间(内存单元),而想要访问这个对象的地址,就需要利用取地址运算符&获取其地址——第一个字节的地址。示例:

     

    1. int a = 10; //a在内存中要分配空间,int类型为4个字节
    2. printf("%p\n", &a); //%p 是专门用来打印地址的
    3. int* pa = &a;

    这段代码中的变量pa是用来存放地址的,在C语言中被称为指针变量(pointer variable),也可以叫指针(pointer)。

    (但指针实际上是一个抽象概念,大部分情况下既可以指指针变量,也可以指地址,如果一时无法理解,最好在使用中逐渐领会,而不要强行下定义。)

    对于这个指针变量,我们会说:pa“指向”a

    声明它时int后的*说明其是指针变量,而int说明pa指向的对象是int类型的。

    指针变量的声明可以和其他变量一起进行:

    int a, b, arr[5], * p;

    并且,指针是可以传递的,将上面的pa的值赋给另一个指针变量,它们将同时指向a

    1. int* pb;
    2. pb = pa;

    获取地址后就能够通过解引用操作符*,来访问地址,对该对象进行操作:

    1. int a = 10;
    2. int* pa = &a;
    3. *pa = 20; //*pa就是通过存储在pa里面的地址找到a
    4. printf("%d\n", a); //20

    因为pa指向a,所以也可以说*paa别名

    *pa不仅值与a相同,实际上本质也相同。对*pa的改变也会产生对a的改变。

    其实倒不如说,改变*pa就是改变a,这一点要千万注意。

    而指针变量本身的大小是多少呢?

    1. printf("%d\n", sizeof(char*)); //4 或 8
    2. printf("%d\n", sizeof(short*)); //4 或 8
    3. printf("%d\n", sizeof(int*)); //4 或 8
    4. printf("%d\n", sizeof(long*)); //4 或 8
    5. printf("%d\n", sizeof(long long*)); //4 或 8
    6. printf("%d\n", sizeof(float*)); //4 或 8
    7. printf("%d\n", sizeof(double*)); //4 或 8

     

    实际上,指针的大小是相同的,因为指针是用来存放地址的,指针需要多大空间,取决于地址的存储需要多大空间——即4或8取决于是32位平台还是64位平台。

    2. 结构体

    结构体(Struct)也叫结构,是C语言的重要知识点,它使得C语言有能力描述复杂类型

    如果有学过JavaScript或其他某些语言,会发现结构体与对象、记录等的概念十分相似,它是可能具有不同类型的值的集合,这些值被称为结构体的成员

    当我们需要存储一组相关数据项,而且这些数据的类型不完全相同时,结构体是理想的选择。

    简单示例:

    1. //模拟一个学生的简单结构体,Stu是student的缩写
    2. struct Stu
    3. {
    4. //成员变量
    5. char name[20];
    6. int age;
    7. double score;
    8. };
    9. int main()
    10. {
    11. struct Stu s = { "张三", 20, 85.5 }; //结构体的创建和初始化
    12. //读取方式1:结构体变量.成员变量
    13. printf("1:%s %d %lf\n", s.name, s.age, s.score);
    14. struct Stu* ps = &s; //结构体类型的指针
    15. //读取方式2:结构体指针解引用.成员变量名
    16. printf("2:%s %d %lf\n", (*ps).name, (*ps).age, (*ps).score);
    17. //读取方式3:结构体指针->成员变量名
    18. printf("3:%s %d %lf\n", ps->name, ps->age, ps->score);
    19. //以上三种读取方式的结果都是 张三 20 85.500000
    20. return 0;
    21. }

    :每个结构体代表一个新的作用域,因此在这个作用域里声明的名字都不会和程序中的其他名字冲突。C语言表述为:每个结构体都为它的成员设置了独立的命名空间(name space)。

  • 相关阅读:
    学习笔记-Speed-Win
    图形系统开发实战课程:进阶篇(上)——6.图形交互操作:拾取
    中集集团全球港航人工智能高科技领军企业中集飞瞳,工业级高性能港航人工智能产品全球规模应用智能化港口船公司铁路堆场海关大幅提效降本
    面试--redis基础
    算法竞赛入门【码蹄集进阶塔335题】(MT2281-2285)
    大语言模型-LLM简介
    优盘数据恢复如何操作?恢复U盘数据的三个简单方法
    09循环嵌套
    【JAVASE系列】14_包装类与日期处理
    js查询月份开始和结束日期
  • 原文地址:https://blog.csdn.net/m0_73088370/article/details/126622031