结构体
#include <stdio.h>
struct weapon{
char name[6];
int atk;
int price;
} ;
int main(){
struct weapon weapon_1 = {"AK47",100,200};
printf("%s\n",weapon_1.name); // AK47
// 结构体指针
struct weapon *w;
w=&weapon_1;
printf("%s\n",(*w).name); // AK47
printf("%s\n",w->name); // AK47
struct weapon weapon_2[2] = {
{"AK48",110,210},
{"AK49",120,220}
};
struct weapon *p;
p = weapon_2;
printf("%s\n",p->name); // AK48
p++;
printf("%s\n",p->name); // AK49
// 总长度:字节对齐
printf("%d\n",sizeof(struct weapon)); // 16:8+4+4
return 0;
}
联合体
#include <stdio.h>
union data{
char a;
int b;
int c;
} ;
int main(){
union data data_1;
data_1.b= 10;
// 变量地址相同
printf("%p\n",data_1.a); // 0000000A
printf("%p\n",data_1.b); // 0000000A
printf("%p\n",data_1.c); // 0000000A
// 总长度为最长变量长度
printf("%lu\n",sizeof(union data)); // 4
return 0;
}
结构体嵌套结构体指针
结构体如下:
struct head{
unsigned int len;
};
struct cmap{
struct head *h;
long key;
float value;
};
像上述这种指针结构体嵌套有指针的,或是但凡有指针的内存分配,都必须为每个指针变量单独分配内存空间!否则运行的时候,程序便会挂掉。
#include <stdio.h>
struct head{
unsigned int len;
};
struct cmap{
struct head *h;
long key;
float value;
};
int init_cmap(struct cmap* cm){
// 需先为指针分配内存
cm->h = (struct head *)malloc(sizeof(struct head));
if( NULL == cm->h ){
return -1;
}
// memset(&(cm->h->len),0,sizeof(unsigned int));
cm->h->len =1;
cm->key = 2;
cm->value = 3;
return 0;
}
int main()
{
struct cmap cm;
init_cmap(&cm);
printf("%hu\n%lu\n%f\n",cm.h->len,cm.key,cm.value);
free(cm.h);
return 0;
}
补充:
若是清0,可以用memset()函数:
int init_cmap(struct cmap* cm){
memset(cm,0,sizeof(struct cmap));
cm->h = (struct head *)malloc(sizeof(struct head));
if( NULL == cm->h ){
return -1;
}
memset(cm->h,0,sizeof(struct head));
return 0;
}
但是注意:
如果是字符数组的话,memset可以随便用,但是如果是其他类型的数组,一般只用来清零,如果是填充数据就不合适了,如:
memset(a, 1, sizeof(a));
想用这个来把a所有元素设置为1,是不成功的,为什么呢?因为memset函数每次填充的数据长度为一个字节,即为0x01,而a的一个元素长度为4个字节,即0x00000000,如果把0x01填充进去,则填充的结果是0x01010101,而不是我们期待的0x00000001,所以是不合适的,多用与结构体清零!且上述场景必须要先将外结构体数据清0,再将结构体内指针清0。
若需要结构体拷贝,可使用memcpy()函数:
void cpy(struct cmap * a, struct cmap * b){
memcpy(a,b,sizeof(a));
//a->h =b->h;
a->key = b->key;
a->value = b->value;
}
但注意:memcpy(a,b,sizeof(a)) 只能拷贝其中的指针对象;
且需注意如用sizeof(b),可能会造成a的内存溢出,例如:char a[100],b[50]; memcpy(a, b, sizeof(b));。
指向结构体的void*指针
void即“无类型”,void *则为“无类型指针”,可以指向任何数据类型。
如果我们用void*指向上述cmap结构体,那么必须先为外层结构体指针分配内存,再为内部节结构体指针分配内存
#include <stdio.h>
struct head{
unsigned int len;
};
struct cmap{
struct head *h;
long key;
float value;
} *cm;
int init_cmap(void **state){
// 需先为外层结构体指针分配内存,再为内部节结构体指针分配内存
cm = (struct cmap *)malloc(sizeof(struct cmap));
cm->h = (struct head *)malloc(sizeof(struct head));
if( NULL == cm || NULL == cm->h ){
return -1;
}
cm->h->len =1;
cm->key = 2;
cm->value = 3;
*state = (void *)cm; //强制转换
return 0;
}
int main()
{
void* state;
init_cmap(&state);
printf("%lu\n%f\n",((struct cmap*)state)->key,((struct cmap*)state)->value); //强制转换
free(cm->h);
free(cm);
return 0;
}