结构体 枚举 typedef
对结构体内存清零:
#include <stdio.h>
#include <string.h>
struct STU
{
int id;
char sex;
};
int main()
{
struct STU s1;
memset(&s1 , 0 , sizeof(s1));
}
![](http://images0.cnblogs.com/blog/660888/201409/032352293283729.png)
结构体内存对齐:
以结构体最长的类型对齐
#include <stdio.h>
#include <string.h>
struct STU
{
char sex;
int id;
};
int main()
{
struct STU s1;
memset(&s1, 0, sizeof(s1)); //把结构体内存清零
s1.id = 0x12345678;
s1.sex = 0x88;
}
此结构体 sizeof = 8 内存如下:
![](http://images0.cnblogs.com/blog/660888/201409/032352298137115.png)
struct STU
{
int id;
// 4字节对齐char name[10];
};
sizeof = 16
struct STU
{
char id; //最长字节就是char 1个字节
char name[10];
};
sizeof = 11
struct STU
{
short id;
char name[10];
};
sizeof = 12
struct STU
{
char * id; // 4
char name[10]; // 12 4字节对齐
};
sizeof = 16
struct STU
{
char id : 2; // 代表 id 是两个 bit 长
};
sizeof = 1
结构体里的类型可以 bit 位 存储
#include <stdio.h>
#include <string.h>
struct STU
{
char id : 2; //两个bit位 如果存4的话就会是0 如果存5的话就会是1
};
int main()
{
struct STU s1;
s1.id = 4;
printf("%d\n" , s1.id);
}
![](http://images0.cnblogs.com/blog/660888/201409/032352301886301.png)
对齐只针对字节,不会针对位来对齐
struct STU
{
char id : 2;
char name : 2;
};
sizeof = 1
struct STU
{
int id : 2;
};
sizeof = 4
struct STU
{
int id : 2;
int age : 2;
};
sizeof = 4
结构体之前的嵌套:
#include <stdio.h>
#include <string.h>
struct A
{
int i;
char c;
};
struct B
{
int i;
struct A a;
};
int main()
{
printf("%d\n" , sizeof(struct B));
}
sizeof = 12
结构体之间的赋值:
结构体之间的赋值 原理就是内存的拷贝。
#include <stdio.h>
#include <string.h>
struct STU
{
char name[1024];
};
int main()
{
struct STU s1 = { "liuwei" };
struct STU s2;
s2 = s1; // memcpy( &s2 , &s1 , sizeof(s1)); 和这句话效果一样
printf("%s\n",s2.name);
}
![](http://images0.cnblogs.com/blog/660888/201409/032352304853042.png)
结构体中 有指针的赋值:
如果是常量字符串,改变一个结构体的值,不会影响另外一个,因为内存中的地址不一样
#include <stdio.h>
#include <string.h>
struct STU
{
char *name;
};
int main()
{
struct STU s1 = { "liuwei" };
struct STU s2;
s2 = s1;
s1.name = "xuanyuan";
printf("%s\n",s2.name);
}
![](http://images0.cnblogs.com/blog/660888/201409/032352307665958.png)
但如果是在堆上开辟的新内存,那么复制的只是那个地址,指向的是同一块内存。如果改变了一个值,另外一个也会改变。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct STU
{
char *name;
};
int main()
{
struct STU s1 , s2;
s1.name = malloc(10);
strcpy(s1.name , "liuwei");
s2 = s1;
strcpy(s1.name , "xuanyuan");
printf("%s\n",s2.name);
free(s1.name);
}
![](http://images0.cnblogs.com/blog/660888/201409/032352311415143.png)
函数体返回结构体,然后赋值其实是内存拷贝 注意这个大坑
#include <stdio.h>
#include <string.h>
struct str
{
char buf[1024];
};
struct str get_str()
{
struct str s;
strcpy( s.buf , "hello world");
return s;
}
int main()
{
struct str tmp = get_str(); //返回的是一个结构体变量,结构体变量之间的赋值,是内存拷贝
printf("%s\n" , tmp.buf);
return 0;
}
![](http://images0.cnblogs.com/blog/660888/201409/032352314535113.png)
注意其他类型变量与结构体之间的区别
#include <stdio.h>
#include <string.h>
char *get_str()
{
char buf[100];
strcpy( buf , "hello world" );
return buf;
}
int main()
{
printf("%s\n" , get_str() ); //输出乱码,因为buf的地址已经被函数释放了
return 0;
}
![](http://images0.cnblogs.com/blog/660888/201409/032352317194800.png)
在退出get_str函数的时候,内存释放,输出乱码。
![](http://images0.cnblogs.com/blog/660888/201409/032352319388499.png)
如果函数实在要返回结构体,就返回结构体指针把
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct str
{
char buf[1024];
};
struct str *get_str()
{
struct str *s = malloc(sizeof( struct str ));
strcpy( s->buf , "hello world");
return s;
}
int main()
{
struct str *tmp = get_str();
printf("%s\n" , tmp->buf);
free(tmp);
return 0;
}
![](http://images0.cnblogs.com/blog/660888/201409/032352322355241.jpg)
返回结构体指针的一种错误方法
#include <stdio.h>
#include <string.h>
struct str
{
char buf[1024];
};
struct str *get_str()
{
struct str s;
strcpy( s.buf , "hello world");
return &s; //虽然返回的是结构体的地址,但是结构体的内存是在栈上,函数结束被释放
}
int main()
{
struct str *tmp = get_str();
printf("%s\n" , tmp->buf);
return 0;
}
枚举的生长规律 是根据前一个值 再+1
#include <stdio.h>
int main()
{
enum color{ red = 11 , yellow = 10 , blue};
printf("%d\n",blue);
return 0;
}
![](http://images0.cnblogs.com/blog/660888/201409/032352325479912.png)
需要注意的是枚举里面是以逗号分隔的,而不是以分号。
typedef的威力:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//这个函数是连接两个字符串
const char *func( const char *str1 , const char *str2 )
{
char *p = malloc( strlen(str1) + strlen(str2) + 1 );
strcpy( p , str1);
strcat( p , str2);
return p;
}
//如果要定义这个函数的 函数指针 如下
const char *(*p)( const char *str1 , const char *str2 );
int main()
{
p = func;
char * s = p("hello","world");
printf("%s\n",s);
return 0;
}
![](http://images0.cnblogs.com/blog/660888/201409/032352328609883.png)
但是这样的函数指针看上去是不是很蛋疼呢?
typedef const char *(*FUNC)( const char *str1 , const char *str2 );
可以用typedef 定义这个 函数指针 类型
方便以后使用