【C语言】第一章:初识C语言(五)

目录

十三、指针

(一)内存

(二)指针变量的大小

十四、结构体

总结


十三、指针

(一)内存

要理解指针,首先我们需要理解内存。内存是计算机上的一种存储空间,在我们的电脑中常见的有8GB/16GB内存。当程序运行时,它会被载入内存,而程序如果有数据需要存储,也会申请内存空间。那么如何有效地使用内存呢?

在生活中,我们有很多的空间,比如楼房,为了方便使用这些空间,我们会对其进行编号,例如龙岩学院格物等等。通过这些编号,我们可以快速找到对应的空间。

计算机也是采用类似的方式,我们将内存想象成一个大长方形,并将其等分为许多小格子,如下图所示:

 

每个小格子被称为一个内存单元,我们可以为每个内存单元分配一个编号,如图中的右侧所示。这样,我们就可以快速找到每个内存单元的位置。

在现实生活中,我们将西安邮电大学A栋教学楼A101称为地址,通过这些地址,我们可以找到所需的空间。而在C语言中,我们也将地址称为指针。

那么,如何生成内存单元的地址(指针)来访问它们呢?

常见的计算机有32位和64位架构(这里的“位”指的是比特位)。尽管64位已成为主流,但为了更好地说明问题,我们这里以32位机器为例。

在32位机器中,有32根地址线(即物理电线)。当这些地址线通电时,会传输出高电平或低电平的信号,并以二进制形式表示,如1和0。这样,我们就得到了一个32位的二进制序列,如下图所示。这些二进制序列与上文中的每个内存编号一一对应,因为二进制与十进制可以相互转换。

因此,这些由32根地址线决定的二进制序列可以用来管理内存,每个序列代表一个内存单元的地址。

 

32位机器最多可以产生2^32个不同的地址,每个地址对应一个内存单元。而每个内存单元的大小为一个字节,所以最多可以管理2^32个字节的内存大小,即4GB。

64位机器已经成为主流,它最多可以控制2^64个字节的内存,即16EB,这已经相当大了。在日常使用中,我们常见的内存容量是8GB或16GB。

通过上述讲解,我们可以更深入地理解内存。内存单元的编号就是地址,而指针是存储内存地址的变量。通过指针,我们可以使用内存地址访问或操作相应内存单元中的数据。

我们来看下面一段代码:

#include<stdio.h>
int main()
{
       int a = 5; // 向内存申请四个字节的空间
       printf("%d", sizeof(a));
       return 0;
}

在这段代码中,我们可以看到变量 a 被定义为整型变量,并且通过 sizeof 运算符获取它所占用的字节数。根据代码的运行结果,我们知道 a 占用了 4 个字节的空间。

通常情况下,我们使用十六进制数来表示内存地址,因为每四位二进制数等于一位十六进制数,可以更清晰地表示地址。需要注意的是,在C语言中,表示十六进制数需要加上前缀 0x。

接下来,让我们打印出变量 a 的地址:

#include<stdio.h>
int main()
{
       int a = 5; // 向内存申请四个字节的空间
       printf("%p", &a);
       return 0;
}

在这段代码中,我们使用 %p 格式说明符将变量 a 的地址打印出来。通过 &a 来获取变量 a 的地址。需要注意的是,每次运行代码,编译器会重新为变量分配内存地址,因此每次打印出来的地址可能不相同。

 

指针是一个用于存储内存地址的变量。让我们来看一下下面的代码:

int main()
{
       int a = 5; // 向内存申请四个字节的空间
       int* pa = &a;

       printf("%p", pa);
       return 0;
}

在这段代码中,我们定义了一个指针变量 pa,它存储了变量 a 的地址。int* 表示 pa 是一个指向整型数据的指针。通过将 pa 与 %p 结合使用,我们可以打印出 pa 中存储的地址。

指针的作用不仅仅是记录变量的地址,还可以通过解引用操作来修改所指向地址的值。例如:

#include<stdio.h>
int main()
{
       int a = 5; // 向内存申请四个字节的空间
       int* pa = &a;

       printf("%d\n", *pa); // 解引用操作,输出 a 的值

       *pa = 10; // 修改 a 的值
       printf("%d\n", a);

       return 0;
}

 

在上述代码中,通过解引用操作 *pa,我们可以获取到 pa 指向的地址中存储的值,即变量 a 的值。我们可以通过修改 *pa 的值来改变 a 的值。

(二)指针变量的大小

我们运行一下下面这段代码

#include<stdio.h>
int main()
{
       int* a;
       char* b;

       printf("%zu\n", sizeof(a)); // 打印指针变量 a 的大小
       printf("%zu\n", sizeof(b)); // 打印指针变量 b 的大小

       return 0;
}

32位机器下结果应该是两个4,64位机器结果是两个8

可见指针变量的大小与其所指向类型无关,只与机器是多少位有关系。

因为指针变量存放的是内存地址,所以在32位环境下,指针的大小为4字节;在64位环境下,指针的大小为8字节。这取决于操作系统和编译器的实现。

十四、结构体

在C语言中,除了内置类型(如int、char、short、long、long long、double、float等),还存在自定义类型,分为三种:结构体、联合体和枚举。本文将重点介绍结构体。

当我们需要描述一个人的身高、体重、姓名、性别和年龄等信息时,或者需要描述一本书的书名、作者、出版社和定价等信息时,这些都属于相对复杂的类型。此时,我们可以使用结构体来处理。

结构体的关键字是struct。下面是一个学生类型的结构体定义:

struct Stu
{
    char name[20];
    char sex[5];
    int age;
};

我们可以使用该结构体进行以下操作:

#include<stdio.h>

struct Stu
{
    char name[20];
    char sex[5];
    int age;
};


int main()
{
    struct Stu s = { "zhangsan", "男", 18 };
    struct Stu s2 = { "lisi", "女", 20 };

    printf("%s\n", s2.name);
    printf("%s\n", s2.sex);
    printf("%d\n", s2.age);

    return 0;

}

main函数中,我们定义了两个结构体变量并对其进行初始化,然后将其打印出来。需要注意的是,我们使用.操作符来访问结构体的成员。

除了使用.操作符,我们还可以使用函数来打印结构体。下面是相应的代码实现:

#include<stdio.h>
struct Stu
{
    char name[20];
    char sex[5];
    int age;
};



void printStu(struct Stu* ps)
{
    printf("%s %s %d\n", (*ps).name, (*ps).sex, (*ps).age);
    printf("%s %s %d\n", ps->name, ps->sex, ps->age);
}



int main()
{
    struct Stu s = { "张三", "男", 18 };
    struct Stu s2 = { "李四", "女", 20 };
    printStu(&s);
    return 0;
}

运行结果如下:

在函数printStu中,我们使用指针方式访问结构体成员,通过(*ps).成员名和ps->成员名两种方式实现了相同的输出效果。

总结

本节我们简要了解指针与结构体。

本章结束,下一站,分支和循环

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值