1数据类型
1.1 数据类型概念
什么是数据类型?为什么需要数据类型?
数据类型是为了更好进行内存的管理,让编译器能确定分配多少内存。
我们现实生活中,狗是狗,鸟是鸟等等,每一种事物都有自己的类型,那么程序中使用数据类型也是来源于生活。
当我们给狗分配内存的时候,也就相当于给狗建造狗窝,给鸟分配内存的时候,也就是给鸟建造一个鸟窝,我们可以给他们各自建造一个别墅,但是会造成内存的浪费,不能很好的利用内存空间。
我们在想,如果给鸟分配内存,只需要鸟窝大小的空间就够了,如果给狗分配内存,那么也只需要狗窝大小的内存,而不是给鸟和狗都分配一座别墅,造成内存的浪费。
当我们定义一个变量,a = 10,编译器如何分配内存?计算机只是一个机器,它怎么知道用多少内存可以放得下10?
所以说,数据类型非常重要,它可以告诉编译器分配多少内存可以放得下我们的数据。
狗窝里面是狗,鸟窝里面是鸟,如果没有数据类型,你怎么知道冰箱里放得是一头大象!
数据类型基本概念:
类型是对数据的抽象;
类型相同的数据具有相同的表示形式、存储格式以及相关操作;
程序中所有的数据都必定属于某种数据类型;
数据类型可以理解为创建变量的模具: 固定大小内存的别名;
1.2 数据类型别名
示例代码:
typedef unsigned int u32;
typedef struct _PERSON{
char name[64];
int age;
}Person;
void test(){
u32 val; //相当于 unsigned int val;
Person person; //相当于 struct PERSON person;
}
1.3 void数据类型
void字面意思是”无类型”,void* 无类型指针,无类型指针可以指向任何类型的数据。
void定义变量是没有任何意义的,当你定义void a,编译器会报错。
void真正用在以下两个方面:
对函数返回的限定;
对函数参数的限定;
示例代码:
//1. void修饰函数参数和函数返回
void test01(void){
printf("hello world");
}
//2. 不能定义void类型变量
void test02(){
void val; //报错
}
//3. void* 可以指向任何类型的数据,被称为万能指针
void test03(){
int a = 10;
void* p = NULL;
p = &a;
printf("a:%d\n",*(int*)p);
char c = 'a';
p = &c;
printf("c:%c\n",*(char*)p);
}
//4. void* 常用于数据类型的封装
void test04(){
//void * memcpy(void * _Dst, const void * _Src, size_t _Size);
}
1.4 sizeof操作符
sizeof是c语言中的一个操作符,类似于++、–等等。sizeof能够告诉我们编译器为某一特定数据或者某一个类型的数据在内存中分配空间时分配的大小,大小以字节为单位。
基本语法:
sizeof(变量);
sizeof 变量;
sizeof(类型);
sizeof 注意点:
- sizeof返回的占用空间大小是为这个变量开辟的大小,而不只是它用到的空间。和现今住房的建筑面积和实用面积的概念差不多。所以对结构体用的时候,大多情况下就得考虑字节对齐的问题了;
- sizeof返回的数据结果类型是unsigned int;
- 要注意数组名和指针变量的区别。通常情况下,我们总觉得数组名和指针变量差不多,但是在用sizeof的时候差别很大,对数组名用sizeof返回的是整个数组的大小,而对指针变量进行操作的时候返回的则是指针变量本身所占得空间,在32位机的条件下一般都是4。而且当数组名作为函数参数时,在函数内部,形参也就是个指针,所以不再返回数组的大小;
示例代码:
//1. sizeof基本用法
void test01(){
int a = 10;
printf("len:%d\n", sizeof(a));
printf("len:%d\n", sizeof(int));
printf("len:%d\n", sizeof a);
}
//2. sizeof 结果类型
void test02(){
unsigned int a = 10;
if (a - 11 < 0){
printf("结果小于0\n");
}
else{
printf("结果大于0\n");
}
int b = 5;
if (sizeof(b) - 10 < 0){
printf("结果小于0\n"