1. 前面说点话
上一个章节
嵌入式Linux:c语言深度解剖(入门篇)
zhuanlan.zhihu.com
写完后,很多看完的人都想把我按在地上摩擦,咬牙切齿不足解恨,但是也有很多人表示支持,在此,鄙人表示感谢。
这个章节说下C语言的关键字
我很想好好说下这个章节,主要是很多人不知道数据如何在内存里面存储的,而且什么是内存,很多初学者也不理解,内存可以理解成很多很多个格子,比如1G的内存,就有1024x1024x1024 byte个格子,每个格子里面都有8个小格子,而且每个格子都有自己的编号,这样想就没那么复杂了,数据类型就是把各种各样的数据保存在这些格子里面。
如何存?怎么存?就跟不同的数据类型有关系了
什么是关键字?
C语言有多少个关键字?
关键字要跟编译器联系起来,比如int关键字,我写了个( int i = 0;)编译器就知道int这个家伙是认识的,编译器就会给int 修饰的变量分配一个房子,比如说这个房子有四个字节。
C语言有32个关键字
2. C语言的关键字(数据类型关键字)
数据类型关键字一共有12个,分别是下面
字符类型
(1) char :声明字符型变量或函数
数值类型
(1) double :声明双精度变量或函数
(2) float:声明浮点型变量或函数
(3) int:声明整型变量或函数
(4) long :声明长整型变量或函数
(5) short :声明短整型变量或函数
构造类型
(1) enum :声明枚举类型
(2) struct:声明结构体变量或函数
(3) union:声明联合数据类型
有符号型和无符号型
(1) unsigned:声明无符号类型变量或函数
(2) signed:声明有符号类型变量或函数
什么是数据类型?
我相信很多人有疑问,或者很多人自信满满觉得自己对数据类型非常懂,在我看来就是由不同的格子组成的,最最最基本的数据类型是char ,char数据类型就有一个格子(一个字节),像下面这样
char数据类型的一个格子
先说char数据类型
这个格子能装多少东西呢?这是我们最想知道的,编译器告诉你这个格子可以装二进制数0B11111111,里面有8个小格子,每个格子里面的东西是未知的。
<img src="https://pic4.zhimg.com/v2-1d8e0ca353ee26aa6a1411a0a3ff849f_b.jpg" data-size="normal" data-rawwidth="84" data-rawheight="88" width="84">
一个格子里面装的东西示意图
如果里面装的是0B11111111,那这个格子应该是这个样子的,对应的十进制就是255
上面说了char,下面说unsigned 和signed
上面说了,一个大格子里面有8个小格子,但是8个小格子是有顺序编号的,就是0~7
比如一个数字0B 11111111 ,这个我们都知道是 =256,
定义
无符号数(unsigned)无符号数只能表示非负数(及正数)。
有符号数(signed)可以表示任何类型规定范围内的数。
8个小格子,我们需要有一个格子来告诉编译器,这个大格子装的数据是有符号型的还是无符号类型。编译器指定最高位的格子第8个格子表示符号位
所以
unsigned char i;
表示的大小是0~255,一共256个数字
signed char i;
表示的大小是- ~ =-128~127,其中包括,也是256个数字
小例子
#include"stdafx.h"
intmain(intargc, char*argv[])
{
unsignedchari =;
signedcharj =;
intk =;
for(k=;k<300;k++)
{
i++;
j++;
printf("%4d %4d\t",i,j);
}
return;
}
从图上可以看到,j最大值是127,i最小值是,i最大值可以达到255,j最小值是-128。
变量在内存里怎么保存的,看看下面这个图片
我们上面把char unsigned signed 搞定之后,我们再来看看其他的数据类型
数值类型
(1) double :声明双精度变量或函数
(2) float:声明浮点型变量或函数
(3) int:声明整型变量或函数
(4) long :声明长整型变量或函数
(5) short :声明短整型变量或函数
既然我们知道了char是一个格子,那么double,float,int,long,short是多少个格子呢?
这时候,我们就需要用到一个关键字sezeof,这个关键字是用来确定对象的大小的,然后我们把上面的代码改一下
#include"stdio.h"
intmain(intargc, char*argv[])
{
charx1 =;
int x2 =;
shortx3 =;
longx4 =;
double x5 =;
floatx6 =;
printf("char %d int %d short %d long %d double %d float %d\n"\
,sizeof(x1),sizeof(x2),sizeof(x3),sizeof(x4),sizeof(x5),sizeof(x6));
return;
}
输出如图
所以我们可以知道
int 类型和long,float类型的格子大小如下
double类型的格子大小如下
short类型的格子大小如下
char类型的格子大小如下
好了,到这里了,大家想想看
char char i = 0 ;
i占领的格子大小有多少呢?有没有这样的写法呢?
看上面的图片,char char i =0;是编译不通过的,但是你想过int int ,long long ,short short,long double呢?
为什么会编译出错呢?
说太多会有别人说我装逼厉害,有一种东西叫做编译器,编译器就像我们人类的法律一样,规定什么可以做什么是违法的,人类有很多种国家的法律,有些国家的法律允许一个老公娶几个老婆,当然,编译器也有很多个,这个自行百度。
说完数值数据类型,下面就开始说
构造类型
(1) enum :声明枚举类型
(2) struct:声明结构体变量或函数
(3) union:声明联合数据类型
先说枚举类型enum
enumunion_type_age{
UNION_AGE_1=10,
UNION_AGE_2,
UNION_AGE_3
}union_var_age;
enum是关键字,union_type_age说明是这个整体,是这个枚举变量的类型,就像一个户口本,有一个户主的名字一样,比如小明家的爸爸叫做小宝,小宝是小明家的户主,别人会这样说,小宝家的小明,小宝家的XX之类的。
里面的UNION_AGE_1=10, UNION_AGE_2, UNION_AGE_3 是这个枚举类型的数值,它们是const常数类型的,只能在初始化的时候取设定它的值。
union_var_age是枚举类型的变量,它的值只能取花括号里面的数据。
用下面的一个小程序理解上面的内容,不理解的请留言
#include"stdio.h"
enumunion_type_age{
UNION_AGE_1=10,
UNION_AGE_2,
UNION_AGE_3
}union_var_age;
intmain(intargc, char*argv[])
{
printf("enum %d\n",sizeof(enum));
union_var_age =UNION_AGE_2;
printf("union_var_age %d\n",union_var_age);
return;
}
再说结构体struct 数据类型
这个关键字的数据类型太厉害了,学过C++都知道C++是面向对象的语言,但是linux内核下面有很多通过c实现面向对象的,其中struct起到了非常重要的作用,struct可以把很多不一样的数据类型统一成一个整体去使用。
#include"stdafx.h"
#include"stdio.h"
structstr_cpu{
intage;
char*name;
doublef;
}str_t;
intmain(intargc, char*argv[])
{
str_t.age =10;
str_t.name ="Linux";
str_t.f =1.077;
printf("str_t.age %d str_t.name %s str_t.f %f\n",str_t.age,str_t.name,str_t.f);
return;
}
跟枚举一样strcpu这个指的是结构体花括号里面的所有东西,结构体变量名字的大小是花括号里面所有变量大小的总和,你可以用sizeof(strcpu)看看它的大小,str_cpu的大小是里面大小的总和(16个字节),但是枚举类型那个名字的大小却不一样,只有他自己的大小(4个字节)。
#include"stdio.h"
intadd(inta,intb)
{
return(a+b);
}
typedefstructstr_cpu{
intage;
char*name;
doublef;
int(*func)(int,int);
}str_t;
str_t m_str_t;
str_t*str_p =&m_str_t;
intmain(intargc, char*argv[])
{
m_str_t.age =10;
m_str_t.name ="Linux";
m_str_t.f =1.077;
m_str_t.func =add;
printf("%d %d %s %f\n",m_str_t.age,m_str_t.func(5,9),m_str_t.name,m_str_t.f);
str_p->age =12;
printf("str_p->age = %d\n",str_p->age);
return;
}
union 数据类型
union数据类型关键字的用法与struct的用法非常相似,union维护足够多的空间来放置成员的一种。
在union中,所有的数据成员公用一个空间,同一个时间只能存储其中一个数据成员,所有成员变量的起始地址都是一样的
#include"stdio.h"
unionCpuMachine
{
charname;
intnumber;
char*str;
doubletime;
}UnionCpu;
intmain(intargc, char*argv[])
{
printf("UnionCpu %d double %d\n",sizeof(UnionCpu),sizeof(double));
ret
urn;
}
看上面的例子,union最大的数据是double ,所以CpuMachine的长度也是double的长度。
但是在内存里如何组织这个大小的呢?
我们用一个视频来体验一下下面的代码
#include"stdio.h"
unionCpuMachine
{
charname;
intnumber;
char*str;
doubletime;
}UnionCpu;
intmain(intargc, char*argv[])
{
UnionCpu.name =0x55;
UnionCpu.number =500;
UnionCpu.str ="Microsoft Visual";
UnionCpu.time =1.5678;
printf("UnionCpu %d double %d\n",sizeof(UnionCpu),sizeof(double));
return;
}
每次单步执行之后,共用体之后的值把之前的值给覆盖了,一个时间点后,共用体只能保存一个值。
问题:
数据类型是有不同大小的格子来组成的,那么不同的数据类型型格子保存在哪里呢?是由谁来决定的呢?
说下下面代码的输出是多少?
#include"stdio.h"
unionCpuMachine
{
inti;
chararray[2];
}UnionCpu;
intmain(intargc, char*argv[])
{
UnionCpu.array[] =0x55;
UnionCpu.array[1] =0x33;
printf("i 0x%x\n",UnionCpu.i);
return;
}
看完觉得有收获的,请帮忙点赞支持