内存四区之一
数据类型本质分析
数据类型概念
- “类型” 是对数据的抽象
- 类型相同的数据有相同的表示形式、存储格式以及相关的操作
- 程序中使用的所有数据都必定属于某一种数据类型
数据类型的本质
- 数据类型可以理解为创建变量的模具;是固定内存大小的别名
- 数据类型的作用:编译器预算对象( 变量 )分配的内存空间的大小
示例:
#include <stdio.h>
int main(void)
{
int a = 10; // 告诉编译器,分配四个字节的内存
int b[10] = { 0 }; // 告诉编译器,分配 4*10 = 40 个字节的内存
printf("b:%p, b+1:%p, &b:%p, &b+1: %p\n", b, b + 1, &b, &b + 1);
// b+1 和 &b+1 的结果是不一样的
// 是因为 b 和 &b 所代表的数据类型不一样
// b 代表数组首元素的地址
// &b 代表整体数组的地址
return 0;
}
数据类型的大小
#include <stdio.h>
int main(void)
{
int a = 10; // 告诉编译器,分配4个字节的内存
int b[10] = { 0 }; // 告诉编译器,分配 4*10 = 40 个字节的内存
printf("sizeof(a):%d\n", sizeof(a));
printf("sizeof(int *):%d\n", sizeof(int *));
printf("sizeof(b):%d\n", sizeof(b));
printf("sizeof(b[0]:%d\n)", sizeof(b[0]));
printf("sizeof(*b):%d\n", sizeof(*b));
return 0;
}
sizeof是操作符,不是函数
sizeof测量的实体大小在编译期就已确定
数据类型的别名
- 可以使用 typedef 给数据类型起别名
- 给结构体起别名:
typedef struct People
{
char name[64];
int age;
}people_t;
- 给 unsigned int 类型起别名:
typedef unsigned int u32;
示例:
#include <stdio.h>
struct People
{
char name[64];
int age;
};
typedef struct People
{
char name[64];
int age;
}people_t;
// 给结构体类型起别名
typedef unsigned int u32; // 给unsigned int 类型起别名;
int main(void)
{
sdtruct People p1;
pople_t p2;
u32 a;
p1.age = 10;
p2.age = 11;
a = 10;
return 0;
}
数据类型的封装
- void 的字面意思是“无类型”,void * 则视为“无类型指针”;void * 可以指向任何类型的数据
用法一:数据类型的封装
例int InitHardEnv(void **handle);
典型的如内存操作函数 memcpy 和 memset 的函数原型原型分别为
void * memcpy(void *dest, const void *src, size_t len);
void * memset(void * buffer, int c, size_t num);
*用法二:void 修饰函数返回值和参数,仅表示无
如果函数没有返回值,那么应该将其声明为 void 型
如果函数没有参数,应该声明其参数为void
示例:
int function(void)
{
return 1;
}
void function2(void)
{
return;
}
- void 指针的意义
C语言规定只有相同类型的指针才可以相互赋值
void* 指针作为左值用于 “接收” 任意类型的指针
void* 指针作为右值赋值给其它指针时需要强制类型转换
示例
int *p1 = NULL;
char *p2 = (char *)malloc(sizeof(char)*20);
- 不存在 void 类型的变量
C语言没有定义void究竟是多大内存的别名
数据类型的总结与拓展
- 数据类型本质是拱顶内存大小的别名;十个模具,c语言规定:通过数据类型定义变量
- 数据类型大小计算 ( sizeof )
- 可以给已存在的数据类型起别名 ( typedef )
- 数据类型封装概念 ( void 万能类型 )