typedef
typedef用于给各种数据类型定义新名字。
他与#define类似,但是有以下不同:
- typdef由编译器解释,而不是预处理器
- typedef只能用于类型的自定义名称,而不能给值进行重命名
- 应该是用typedef给类重命名,而不是#define因为宏定义无法处理指针类型
使用
typedef unsigned char BYTE; //把unsigned char 重新自定义名称为BYTE
BYTE x; //声明一个char变量,此句同 unsigned char x;
也可以使用#define来定义
比如使用
#define BYTE unsinged char
他和上面typedef一样。
和define区别
- 可以使用其他类型说明符对宏类型名进行扩展,但对 typedef 所定义的类型名却不能这样做
#define INTERGE int
unsigned INTERGE n; //没问题
typedef int INTERGE;
unsigned INTERGE n; //错误,不能在 INTERGE 前面添加 unsigned
- 连续定义区别
但是我们看另一个定义
typedef char * STRING
#define char * STRING2
STRING name, sign; //相当于char *name, char *sign;
STRING2 name, sign; //相当于char *name, sign.
看上面对比,发现这样声明则#define在某些情况下起不到我们预期的作用。
用于数组
http://m.biancheng.net/view/2040.html
typedef char ARRAY20[20];
//下面两个声明相同
ARRAY20 a1, a2, s1, s2;
char a1[20], a2[20], s1[20], s2[20];
这里表示ARRAY20是char[20]的别名,表示一个char类型大小为20的数组。
用于指针
typedef int (*PTR_TO_ARR)[4];
PTR_TO_ARR p1, p2;
表示 PTR_TO_ARR 是类型int * [4]的别名,它是一个二维数组指针类型.
用于结构体
//这里的 complex可以省略
typedef struct complex {
float real;
float imag;
} COMPLEX;
COMPLEX a; //定义变量a,等同于 stuct complex a;
struct book {
char title[MAXTITL];
char author[MAXAUTL];
float value;
} lib;
这里和结构体就不同了,结构体的下面lib是创建一个变量,而这里的COMPLEX是一个类型别名,并未创建变量。
可以看到使用COMPLEX可以方便的创建一个struct complex类型。
当有typedef的时候可以我们有两种方式创建complex的结构变量:
- struct complex a;
- COMPLEX a;
但是当省略complex的时候,就只能用COMPLEX a来创建变量了。
对齐特性
http://t.zoukankan.com/axjlxy-p-15008070.html
https://www.jianshu.com/p/9a4f7416bef2
二进制输出
C语言将整数转化成其他进制,其中只有
printf
输出十进制:%d;
输出八进制:%o;
输出十六进制:%x;
而并没有这种二进制对应的格式。
所以我们想直观看到二进制数我们可以将整数转换成对应进制的字符串。
使用itoa函数可以方便的转换。但是itoa的可移植性差,有些编译器不支持。
我们可以自己写一个将整数转换成二进制数字符串的函数
char * itobs(int n, char* ps) {
int i;
const static int size = 8 * sizeof(int);
printf("size: %d\n", size);
//将n和mask1做&,得到最低位的值并+‘0’得到字符0或者1
//然后n右移一位,再看最低位
for (int i = size-1; i >=0; i--, n>>=1) {
ps[i] = (n & 1) + '0'; //将n的
}
ps[size] = '\0';
return ps;
}
int main()
{
char c[40];
itobs(10, c);
printf("%s",c);
return(0);
}
//size: 32
//00000000000000000000000000001010