在 Keil MDK 开发环境中,经常会遇到类似于unsigned int 8、uint8_t 、u8等数据变量定义,对于初学者来讲确实是有点痛苦,后来查询发现以上三种方式均表示——无符号的8位整形数据。
由于C语言类型的长度完全由编译器决定,char 通常被定义成 8 位宽;int 通常被定义成 16 位或 32 位宽(或更高),它取决于平台(编译器将在这两者间选择最合适的字宽);short 通常被定义成 16 位宽;long 通常被定义成 32 或 64位宽。
所以 C99 中引进了一个标准C库头文件 stdint.h ,方便精确确定整数类型的宽度
定义标准的扩展整数类型_stdint.h文件(部分)
/* Signed. */
/* There is some amount of overlap with <sys/types.h> as known by inet code */
#ifndef __int8_t_defined
# define __int8_t_defined
typedef signed char int8_t; //标准表达方式 signed char 被等同于 int8_t;
typedef short int int16_t;
typedef int int32_t;
# if __WORDSIZE == 64
typedef long int int64_t;
# else
__extension__
typedef long long int int64_t;
# endif
#endif
/***************************************/
/* Unsigned. */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
#else
__extension__
typedef unsigned long long int uint64_t;
#endif
/***************************************/
/* Small types. */
/* Signed. */
typedef signed char int_least8_t;
typedef short int int_least16_t;
typedef int int_least32_t;
#if __WORDSIZE == 64
typedef long int int_least64_t;
#else
__extension__
typedef long long int int_least64_t;
#endif
/***************************************/
/* Unsigned. */
typedef unsigned char uint_least8_t;
typedef unsigned short int uint_least16_t;
typedef unsigned int uint_least32_t;
#if __WORDSIZE == 64
typedef unsigned long int uint_least64_t;
#else
__extension__
typedef unsigned long long int uint_least64_t;
#endif
/***************************************/
/* Fast types. */
/* Signed. */
typedef signed char int_fast8_t;
#if __WORDSIZE == 64
typedef long int int_fast16_t;
typedef long int int_fast32_t;
typedef long int int_fast64_t;
#else
typedef int int_fast16_t;
typedef int int_fast32_t;
__extension__
typedef long long int int_fast64_t;
#endif
/***************************************/
/* Unsigned. */
typedef unsigned char uint_fast8_t;
#if __WORDSIZE == 64
typedef unsigned long int uint_fast16_t;
typedef unsigned long int uint_fast32_t;
typedef unsigned long int uint_fast64_t;
#else
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;
__extension__
typedef unsigned long long int uint_fast64_t;
#endif
/***************************************/
/* Types for `void *' pointers. */
#if __WORDSIZE == 64
# ifndef __intptr_t_defined
typedef long int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned long int uintptr_t;
#else
# ifndef __intptr_t_defined
typedef int intptr_t;
# define __intptr_t_defined
# endif
typedef unsigned int uintptr_t;
#endif
/***************************************/
/* Largest integral types. */
#if __WORDSIZE == 64
typedef long int intmax_t;
typedef unsigned long int uintmax_t;
#else
__extension__
typedef long long int intmax_t;
__extension__
typedef unsigned long long int uintmax_t;
#endif
*_t结尾的类型,可以理解为type/typedef的缩写,就是一个结构标注,表示是通过typedef定义的,而不是其它数据类型。(程序的可扩展性)
无符号类型 可表示 unsigned char u8 unsigned short u16 unsigned int u32 这样定义的好处在于使用时不会感觉太混乱,从而能有效的维护代码。
类 型 说 明 | typedef |
---|---|
准确长度类型 | intN_t(N为类型宽度) |
最小长度类型 | int_leastN_t |
快速长度类型 | int_fastN_t |
指针长度类型 | intptr_t |
最大长度类型 | intmax_t |
- 类型说明
- int_least16_t : 指获得一个当前平台所支持的至少有 16 位宽的最短整数类型。
- int_fast32_t : 指获得当前平台下需要处理速度最快的至少为 32 位的整数类型。
- intmax_t : 指获得当前平台所支持的最大宽度的整数类型。
- intptr_t (无符号uintptr_t): 为安全跨平台编程的保证,对于写跨 64 位平台的程序非常重要,是指针和整数之间的转换经常用到(多用于需要精确控制数据在内存中的精确布局时)。换句话说,当需要把指针作为一个整数来运算时,转换成intptr_t才是安全的,然后在运算完毕后再安全的转回指针类型。
无符号整形对应的*_t类型 | 字 宽 |
---|---|
uint8_t | 1字节 |
uint16_t | 2字节 |
uint32_t | 4字节 |
uint64_t | 16字节 |
int64_t \ uint64_t 大数输出 | 格式 |
---|---|
int64_t | %lld |
uint64_t | %llu |
uint64_t | %llx(十六进制) |
uint64_t | %llo (八进制) |
volatile
作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
俗称禁止程序优化,一般在进行多线程程序设计时加,就是在有中断的程序中常见,并且是中断程序所用变量一般用这个加以修饰。
简单的说,就是不让编译器进行优化,即每次读取或者修改值的时候,都必须重新从内存或者寄存器中读取或者修改。
volatile一般用在以下三个方面:
中断标志位
多线程共享的变量
状态寄存器
const
是一个C语言的关键字,它限定一个变量不允许被改变
只读变量,即变量保存在只读静态存储区。编译时,如何尝试修改只读变量,则编译器提示出错,就能防止误修改。
const与define
- 两者都可以用来定义常量,但是const定义时,定义了常量的类型,所以更精确一些(其实const定义的是只读变量,而不是常量)。
- #define只是简单的文本替换,除了可以定义常量外,还可以用来定义一些简单的函数,有点类似内置函数。
- const和define定义的常量可以放在头文件里面。(小注:可以多次声明,但只能定义一次)
const与指针
int flag;
const int * p1=&flag; //p1可变,*p1不可变 const 修饰的是 *p1,即*p1不可变
int * const p2=&flag; //p2不可变,*p2可变 const 修饰的是 p2,即p2不可变
const int *const p3=&flag; //p3不可变,*p3也不可变 前一个const 修饰的是 *p3,后一个const 修饰的是p3,两者都不可变