1.联合跟结构体区别:
联合的定义跟结构体相似,
union 联合名{
数据类型 成员名;
数据类型 成员名;
}联合变量名;
几个变量公用一个内存位置,在不同的时间保持不同的变量;编译时自动产生一个最大的变量长度;
例如:
struct{
int age;
char *addr;
union{
int i;
char *ch;
}x;
}y[10];
访问时:y[1].x.i ,*y[1].x.ch
例如:
main()
{
union{
int i;
struct{
char first;
char second;
}half;
}number;
nubmer.i=0x4241;
printf("%c%c\n",number.half.first,number.half.second);
number.half.first='a';
number.half.second='b';
printf("%x\n",number.i);
getch();
}
output: AB
6261;
分析:给i 赋值时,低八位和高八位也分别是first和second的值,反之这两个字符的ASCII码也作为i 的低八位和高八位
2.restrict用法
类型限定符,用于告诉编译器,该对象已经被指针所引用,只能通过该指针来修改这段地址所指向的内容;
这样就意味着:不能有其它指针指向该段地址空间(无效指针),编译器可以来尽情优化,
例如:(对于编译器来说)
int arr[10];
int* restrict restar=(int*)malloc(10*sizeof(int)); (restar是访问malloc分配空间的唯一方式)
int *par=arr;
for(int i=0;i<10;i++)
{
par[i]+=5;
arr[i]*=2;
restrict[i]+=5;
par[i]+=3;
restrict[i]+=3;
}
对于这段代码,由于restar由restrict限定,则可以优化为restar[i]+=8,而par[i]+=8不成立,因为中间有arr[i]*=2;
故restrict限定后,由于不存在其他修改该段内存的方式,编译器可以尽情来优化代码
再例如:(对于用户来说)
两个copy函数
void *memcpy(void* restrict s1,const void* restrict s2,size_t n);
void *memmove(void* s1,const void* s2,size_t n);
memcpy假定s1,s2没有重叠区域,而memmove是将s2先复制到一个临时空间,再复制到s1,
如果又重叠区域时使用memcpy,则结果是不可预知的。
总结:restrict限定符,对于编译器来说,是让编译器可以自由地去做一些优化;对于用户来说,是告诉用户一些限制,
如果越过限制,编译器不会报错,但结果就又风险了,例如memcpy。