初识C的第五课

目录

指针

1.内存

(1)先理解一下指针

(2)打印a的地址再次理解 

 (3)指针变量的使用

 (4)解引用操作

(4)指针小总结

2.指针变量的大小

结构体

结束语


指针

1.内存

(1)先理解一下指针

我们假设内存是一个大长方形,然后我们对其进行等分,然后我们将每一个小格子称作内存单元,我们可以对每一个内存单元进行编号,实践中,每一个内存单元的大小是一个字节,我们将右边的称作内存单元编号,也就是地址,而在C语言中地址就是指针的意思。

 那是怎么产生内存单元的地址的呢

先说32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0)

那么32根地址线产生的地址就会是:

00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000001

...

11111111 11111111 11111111 11111111

这里就有2的32次方个地址。

2的32次方字节内存大小我们换算一下

2^32Byte == 2^32/1024KB ==2^32/1024/1024MB==2^32/1024/1024/1024GB == 4GB

因此2的32次方字节等于4GB

也就是说32位机器最多拥有4GB内存,这也就是为什么我们以前最常见到的内存是4GB的一个原因。而对于64位的机器,就是相同的计算原理。

这里我们就明白: 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以 一个指针变量的大小就应该是4个字节。 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。

总结: 指针是用来存放地址的,地址是唯一标示一块地址空间的。 指针的大小在32位平台是4个字节,在64位平台是8个字节。

(2)打印a的地址再次理解 

在这里我们有个习惯,因为使用32个二进制位(也就是比特位)表示内存单元的编号,太过于冗杂,由于四位二进制数等于一位十六进制数,于是我们采用十六进制数来表示内存,这样我们就只需要八个数字即可清晰的表示出地址,也就是我们c语言中的指针。

//&a的意思是取出a的地址,%p是打印地址的意思
#include<stdio.h>
int main()
{
	int a = 1;//向内存申请四个字节的空间
	printf("%p", &a);
	return 0;
}
//那里有一个x86和x64的选项,其中x64是64位环境,x86是32位环境
//32位打印出来是8个十六进制的数,64位打印出来是16个十六进制数

 运行后,我们会发现,只打印出来了一个地址,但是我们的a占了四个字节,也就是四个内存单元,应该占据了四个地址,那我们这个地址是这四个地址中的哪一个呢?

我们调试打开内存窗口

 选择内存1,列选择4,我们得到这样一个结果

 左边是内存得到地址,后面是内存的数据,两个为一个字节。

当我们选择列数为1的时候

前四个就是我们申请的四个字节,后面竖着排的就是所存的数据,每一个就是一个字节,前面对应就是地址,所以我们打印出来的a的地址,是我们申请的四个字节中的第一个字节的地址。

结论:a的地址为它所占的几个内存单元中最小的地址,也就是第一个字节的地址,这是一个很重要的结论。

 (3)指针变量的使用

int main()
{
	int a = 1;      // 定义的时候向内存申请4个字节

	int * pa = &a   // pa 是一个变量,是用来放地址的,又叫指针
	                // 所以 pa 叫指针变量,存放指针
	                // int a 后就是申请四个字节	,这四个字节叫 a	
					// 前面的int代表着pa这个指针(地址)指向的是一个int类型
					// *告诉我们pa是指针,前面的int告诉我 pa 指向的是int类型的变量
                    // 合起来pa的类型我们称作int*
	                // &取地址操作符
					// &a取出的是a所占内存的4个字节中的第一个字节
    
	printf("%p\n",&a);
	printf("%p\n",pa);     //打印的时候是一样的这俩
}

 这段代码中,我们创建了a,并申请了四个字节的空间,然后我们使用一个变量pa来存放a的地址,这个变量pa就叫做指针,pa因为也是一个变量,所以我们习惯上叫它为指针变量。pa前面的那颗*表示pa是一个指针,而前面的int代表着pa这个指针(地址)指向的是一个int类型,所以合起来pa的类型我们称作int*,也就是所谓的指针类型。

 (4)解引用操作

那么我们使用指针变量可不仅仅只是记录一下a的地址什么的,我们是需要通过这个地址来改变它里面的数据。这才是指针的用处。

int * pa = &a;       // 知道了pa,怎么找到a,加个*
    *pa = 20;        // 解引用操作 - 作用就是通过pa中的地址,找到a, *pa就是a
                     // 相当于pa就是变量,只有加上*后才能作为指针找到a的地址进行修改
	                 // &a 取出的地址存放到变量pa里,
                     // 对pa前加上*,通过pa这个指针变量存的地址,找到a进行更改
printf("%d\n", a);   // 打印的时候就是20,相当于把a变为20

如图所示,这个*pa中,*的意思是解引用,也就是说这个操作可以使我们通过pa这个地址找到a的值。然后我们对其赋值,从而篡改了a的值,此时a的值已经变成了20

int main()
{
	char ch = 'w';                    
	char* pc = &ch;          // &ch 取出的地址存放到变量pa里,对 pa 前加上*
                             // 通过 pa 这个指针变量存的地址,找到 ch 进行更改
	                         // 通过pc把ch的值改'b'
	*pc = 'b';               // 这个时候把*pc改为b,就是通过pa的地址
                             // pa加上*就是去找到这个地址上的数w,改成b
	printf("%c\n", *pc);//b

	ch = 'q';                // 直接改ch的值,当我的 pc 指向 ch 时候,*pc 就是跟 ch 是一回事
	printf("%c\n", *pc);//q

	return 0;
}

这里用char也是相同的道理,再加深理解一下。

(4)指针小总结

1. 指针就是地址

2. 口头语中指针一般指的是指针变量

#include <stdio.h>
int main()
{
 int num = 10;
 &num;    //取出num的地址
	      //注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)

 printf("%p\n", &num);  //打印地址,%p是以地址的形式打印
 return 0;
} 

//对于变量取地址,存放到指针变量里,然后用解引用操作符,但是*跟前面的类型一起的
//就是char*  int*  后面加指针变量,让其成为解引用

2.指针变量的大小

#include<stdio.h>
int main()
{
	int* a;
	char* b;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(b));
	return 0;
}

指针变量的大小取决于存的是什么

指针变量是用来存放地址,而地址

在32位机器上,就是32个比特位,

指针变量存放的是32bite的地址,指针变量的大小是4个字节

在64位机器上,就是64个比特位,

指针变量存放的是64bite的地址,指针变量的大小是8个字节

结构体

C语言中有很多就是自带的内置类型

还有很多的自定义类型:结构体,枚举,联合体

而结构体的关键字:struct

struct 结构体名
{
   成员列表(可以是基本的数据类型,指针,数组或其他结构类型)
};

上面就是最基础的设置

 结构体由:(1)结构体标签 (2)结构体成员  (3)结构体变量组成

注意:

(1)、关键字struct是数据类型说明符,指出下面说的是结构体类型;

(2)、标识符Student是结构体的类型名;

(3)、最后的分号一定要写;

#include <stdio.h>
struct Stu         //这是一个类型,stu是名字
{
    char name[20];  //这是定义结构体,里面包含的变量进行存储
    char sex[5];
    int age;
};

void print(struct Stu* ps)  //结构体加个*就是结构体的指针,ps是指针变量
{                           //ps得到了s的地址,现在ps就指向这个s
    printf("%s %s %d\n", (*ps).name, (*ps).sex, (*ps).age);
    //打印的时候,*ps就是s,找到s的成员,就是*ps加上.  ,结构体的指针解引用一下,
    //找到了指向的对象s,s成员加上.就能找到了,结构体的地址传过去
    
    //第二种表示
    printf("%s %s %d\n", ps->name, ps->sex, ps->age);
    //ps指向了s,ps指向了name,就是ps指向的s对象里面成员name
    //->  就是结构体的指针->成员名
}
int main()
{
    int num = 0;
    struct Stu s = {"张三","男",20};   
    //用类型创建个变量
    //前面是类型,用类型创建的变量是s,后面是初始化,对于s的初始化
    struct Stu s2 = {"如花","女",18};
    printf("%s\n", s2.name);
    printf("%s\n", s2.sex);
    printf("%d\n", s2.age); 
    //想得到结构体里的成员就是加个 . 后面跟上自己定义成员名
    //结构体变量.成员名来引用或者打印

    print(&s);   
    //先取地址,取出来放到指针里面,然后上面的函数搞个指针
    //&s,取地址s,拿到他的地址,现在把地址交给print了
    //需要写个print函数来打印,这个地址存到指针变量里面了

    return 0;

}

 在主函数中调用的时候,记得加上{},并给他一个变量,这样好去打印,引用,而在变量后加个 .就是找到自己定义的结构体中的成员名。

主函数中是打印的s2,还有s是由上面的函数来打印

下面我们来看s,s在主函数中是用print来取的地址,然后在外面定义函数来引用,并且用指针找地址,结构体加个*就是结构体的指针,ps是指针变量,ps得到了s的地址,现在ps就指向这个s,

下面的print(&s)取地址,上面的struct Stu *ps    就是ps指针指向s的地址,再进行操作。

两种表示

(1)(*p). 成员名(.的优先级高于*,(*p)两边括号不能少)

(2)   p->成员名(->结构体的指针指向成员名)

结构体很多表示,都在这个代码里,详细看看代码,后续会有更详细的介绍。

结束语

到这里,我们已经初始C语言了,下面我们开始C语言的初阶学习,大家保持关注!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
该资源内项目源码是个人的程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值