学习笔记:对C语言中常用数据类型的理解(或者对编程的理解)

在C语言中,有很多极易混淆的概念(比如:内存和指针、函数指针、指针函数、数组指针、指针数组),也正是这些概念使得很多人学习起来很累,今天,笔者分享一下自己对这些的概念的理解。

一、定义

1、内存:随机存取存储器,也叫主存,是与CPU直接交换数据的内部存储器。

2、指针:是编程语言中的一类数据类型及其对象或变量,用来表示一个存取器地址,这个地址的值直接指向存在该地址对象的值。

3、函数指针:是一种在C、C++(类C语言)中指针,可以像一般的函数一样传参、调用、返回变量。

4、指针函数:返回值是一个指针的函数称为指针函数。

5、数组指针:当数组名作为取地址&运算符的操作数,则表达式的值为指向整个数组的指针

6、指针数组:一个数组,数组中的各个元素都是指针。

二、理解

关键:代码中一切都是数据,而数据只有两个属性:首地址和长度,至于怎么读取这个数据与数据本身无关。

如果你理解了上面这一句话,那么C语言中很多看似复杂的概念就很好理解了,那么接下来,我们来看下面这几句古文。

① 下雨天留客天留我不留

     这句话可以拆解成很多总句式:最常见的就是“下雨天,留客天,留我不?留!”,“下雨天留客,天留我不留。”。

② 黄河远上白云一片孤城万仞山羌笛何须怨杨柳春风不度玉门关

     上面这一段古文是一段千古佳话,传闻纪晓岚为人画扇,写下了上面这一段文字,要知道当时是没有标点符号的,所以纪晓岚也是写得一手大板书,细心的朋友可能已经发现了,如果纪晓岚写得是王之涣的《凉州词》,那么他少些了一个“间”字,王之涣的《凉州词》原文是:

黄河远上白云间,一片孤城万仞山。

羌笛何须怨杨柳,春风不度玉门关。

这个问题也是立马就被纪晓岚的朋友发现了,当即指了出来,纪晓岚心想,这回可是糗大了,但是细细一看,纪晓岚灵机一动,立马把这个尴尬的词给圆了过去:

黄河远上,白云一片,孤城万仞山。

羌笛何须怨,杨柳春风,不度玉门关。

 

古代汉语没有标点符号,写在纸上,就如同数据(0和1)存储在内存中,从上面我们可以知道:同一段内存空间,我们不同的读法,读取到的结果是不一样的,按照王之涣《凉州词》的读法,纪晓岚很明显就是错的,如果按照纪晓岚的那个读法,又是合情合理,也符合断句,也是朗朗上口。再者就是都是从“下”字(首地址)开始读,一次读取三个字是“下雨天”,一次读取五个字就是“下雨天留客”。如果把“下”字(首地址)比作内存地址(0xA12D1000)呢?你又能有什么体会?

一:数据 = 首地址 + 长度

二:所有的数据类型本质上就两种:单字节数据、多字节数据。

从这个角度去从新理解上面的定义:

1、内存:一个或者一组容器,能够存取数据的容器。

2、指针:一个首地址。

3、函数指针:  一个首地址。

4、指针函数:返回  首地址 的函数。

5、数组指针:一个首地址

6、指针数组:一个数组,数组中的各个元素都是首地址。

 

这样一来,你会发现上面的很多定义都成了首地址,既然都是首地址,那么那么他们的区别就是长度读取方式的不同了。

这里需要面对一个不可逃避的问题:首地址也是一个数据。

相信很多人,又会开始疑惑了,如果首地址也是一个数据,数据又只是首地址和长度......,那这岂不是成了无底洞?

我的答案是,不是这样的,内存中每一个字节都有自己的唯一的地址,地址是唯一的,不过从某个地址上开始存储多少个字节的数据,这个数据是可变的,既然是可以变动的,那么自然也是可以吧另一个地址的值存到这里来。

那我们再次更新一下上面的理解

1、内存:存取所有的数据或者一段数据的容器。

2、指针:数据。

3、函数指针:  数据。

4、指针函数:返回  数据 的函数。

5、数组指针:数据

6、指针数组:一个数组,数组中的各个元素都是数据。

 

帮助理解(切记,不要在实际运用中使用):

 

using namespace std;

//定义一个函数指针
typedef void(*pFUNCTION)(void);	

void HelloWord(void)
{
	cout << "Hello Word!" << endl;
}

void GoodBye(void)
{
	cout << "Good Bye!" << endl;
}


int main(int argc, char** argv)
{
	pFUNCTION hello = HelloWord;
	pFUNCTION bye = GoodBye;

	//可以理解为,从函数void HelloWord(void)的首地址按照 int类型 的方式读取四个字节
	int addrHello = (int)hello; 
	int addrBye = (int)bye;

	int myarray[2] = { addrHello, addrBye };

	//从addr内存中的首地址开始按照 pFUNCTION类型 的方式读取一定长度的数据
	pFUNCTION helloInt = (pFUNCTION)addrHello;
	pFUNCTION byeInt = (pFUNCTION)myarray[1];
	pFUNCTION byeInt1 = (pFUNCTION)*(myarray + 1);

	helloInt();
	byeInt();
	byeInt1();

	//你甚至可以这么干,当然,能不能运行我就不管了。
	pFUNCTION func = (pFUNCTION)65536;
	func();

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值