C语言数据类型及typedef下的uint8_t / uint32_t


前言

在基于C语言的代码中总能看到uint8_t / uint16_t / uint32_t /uint64_t的身影。如:uint32_t a = 300;
但它似乎又不属于C语言中的6种基本数据类型(short、int、long、char、float、double),那么它是一种新的数据类型?

本文以这个问题为切入点,回顾了C语言中的6种基本数据类型;描述了数据类型在不同编译器、平台存在的字长差异;进而引出了uint8_t / uint16_t / uint32_t /uint64_t的来源和作用;最后介绍了typedef的用法及与define的区别。


一、C语言基本数据类型

C语言共有6种基本数据类型,分别是:

1)整型:short、int、long;

2)浮点型:float、double;

3)字符类型:char。

二、数据类型在不同编译器下存在的字长差异

C语言的6种基本数据类型中,int类型(整型-short、int、long)比较特殊,其具体的字节数同机器字长和编译器有关。下面对比数据类型在16位、32位、64位编译器下的字节长度,用sizeof( )函数得出。

注:
① 这里的编译器位数指的是编译生成的软件(应用程序)的位数;
② char型从本质上说,也是种整型类型,它是长度为1的整数,通常用来存放字符的ASCII码。

16位编译器:

char 			// 1个字节
char*           // 2个字节(*指针变量) 
                // 16位的寻址空间是2^16, 即16个bit,即2字节。(32位、64位编译器同理)
                
short int       // 2个字节
int             // 2个字节
unsigned int    // 2个字节 无符号整型

float           // 4个字节
double          // 8个字节

long            // 4个字节
long long       // 8个字节
unsigned long   // 4个字节

32位编译器:

char           // 1个字节
char*          // 4个字节(*指针变量)(16&32&64位机各不相同)

short int      // 2个字节
int            // 4个字节(16位-2B,32&64位-4B(Byte))
unsigned int   // 4个字节(16位-2B,32&64位-4B)

float          // 4个字节
double         // 8个字节

long           // 4个字节(16&32位-4B,64位-8B)
long long      // 8个字节
unsigned long  // 4个字节(16&32位-4B,64位-8B)

64位编译器:

char            // 1个字节
char*           // 8个字节

short int       // 2个字节
int             // 4个字节
unsigned int    // 4个字节

float           // 4个字节
double          // 8个字节

long            // 8个字节
long long       // 8个字节
unsigned long   // 8个字节

如上所示,int,long int,short int的数据位宽与编译器有关。但存在以下原则(ANSI/ISO制订),即
1) sizeof(short int) <= sizeof(int) ;
2) sizeof(int) <= sizeof(long int) ;
3) short int至少应为16位(2字节) ;
4) long int至少应为32位。

三、uint8_t / uint16_t / uint32_t /uint64_t的来源和作用

1、来源
*_t表示该标识由typedef定义得到,是结构的一种标注。C语言代码中的uint8_t / uint16_t / uint32_t /uint64_t都不是新的数据类型,而是通过typedef给数据类型起得新名字,如:

typedef signed char             int8_t;
typedef short int               int16_t;
typedef int                     int32_t;

2、作用
1)增加代码的可读性
uint8_t,uint32_t能更明显的显示所占字节数。
uint8_t表示占1个字节(1 字节=8 bit);
uint32_t表示占4个字节(4 字节=32 bit)。

2)增加代码的可维护性
在涉及到跨平台时,不同的平台会有不同的字长,所以利用预编译和typedef可以方便的维护代码。

注:uint8_t实际上就是一个char,所以输出 uint8_t类型的变量实际上输出对应的字符,而不是数值,如:

uint8_t  num=67;
cout << num << endl;		//输出结果为C

四、typedef的用法及与define的区别

1、typedef的用法
typedef并不创建新的类型,而仅仅为现有类型添加一个别名。常用于创建易于记忆的类型名称,用它来表示我们的真实意图,如

typedef int                     int32_t;
// typedef定义了一个int的同义字int32_t,可在任何需要int的上下文中使用int32_t。

2、typedef 与define 的区别
1)typedef 行为有点像 define 宏,用其实际类型替代同义字;
2)不同点是typedef 在编译时会被解释,因此让编译器来应付超越预处理器能力的文本替换,即不是简单的文本替换
3)#define优势:可以使用#ifdef ,#ifndef等来进行逻辑判断,使用#undef来取消定义。
4)typedef优势:它受范围规则约束,使用typedef定义的变量类型其作用范围限制在所定义的函数或者文件内(取决于此变量定义的位置),而宏定义则没有这种约束。

案例一:

typedef char *pStr;
define pStr char *;

通常来说,上面两种定义pStr数据类型的方法中,typedef要比 define宏要好,特别是在有指针的场合。请看例子:

typedef char *PSTRING1;
#define PSTRING2 char *;
PSTRING1  p1, p2;
PSTRING2  p3, p4;

在上述的变量定义中,p1、p2、sp3都被定义为char *,p4则定义成了char,而不是我们所预期的指针变量,根本原因在于 define 只是简单的字符串替换;而 typedef 则是为一个类型起新名字。
注:使用 #define 定义时,如果定义中包含表达式,必须使用括号,即 #define f(x) (xx) ;

案例二:

typedef char * pStr;
char string[4] = "abc";
const char *p1 = string;
const pStr p2 = string;
p1++;
p2++;

上述代码中 const pStr p2 并不等于 const char * p2;
const pStr p2:限定数据类型为char *的变量p2为只读,因此p2++错误;
const char * p2(const修饰的是前面的char):可以对任意位置(非系统敏感区域)进行“只读” 操作。(“只读”是相对于char * p2来说所限定的内容)。

总结

1) C语言共有6种基本数据类型:short、int、long;float、double;char;
2) 数据类型(int类型(整型-short、int、long)比较特殊),其具体字节数与编译器位数有关;
3) uint8_t / uint16_t / uint32_t /uint64_t不是新的数据类型,而是通过typedef给数据类型起的新名字;
4) typedef的合理运用可增加代码的可读性、可维护性;
5) typedef不是简单的文本替换,#define 定义时,如果定义中包含表达式,必须使用括号,即 #define f(x) (xx) 。

参考:
https://blog.csdn.net/mary19920410/article/details/71518130
https://blog.csdn.net/bzhxuexi/article/details/19551979
https://blog.csdn.net/qq_44770155/article/details/90602325

猜你喜欢

转载自blog.csdn.net/m0_64770246/article/details/124209343