首页 > 代码库 > 9.3 结构体 枚举 typedef

9.3 结构体 枚举 typedef

对结构体内存清零:
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct STU
  4. {
  5. int id;
  6. char sex;
  7. };
  8. int main()
  9. {
  10. struct STU s1;
  11. memset(&s1 , 0 , sizeof(s1));
  12. }



结构体内存对齐:

以结构体最长的类型对齐
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct STU
  4. {
  5. char sex;
  6. int id;
  7. };
  8. int main()
  9. {
  10. struct STU s1;
  11. memset(&s1, 0, sizeof(s1)); //把结构体内存清零
  12. s1.id = 0x12345678;
  13. s1.sex = 0x88;
  14. }
此结构体  sizeof  = 8  内存如下:



  1. struct STU
  2. {
  3. int id;        // 4字节对齐
  4. char name[10];
  5. };
sizeof  = 16


  1. struct STU
  2. {
  3. char id; //最长字节就是char 1个字节
  4. char name[10];
  5. };
sizeof  = 11


  1. struct STU
  2. {
  3. short id;
  4. char name[10];
  5. };
sizeof  = 12


  1. struct STU
  2. {
  3. char * id; // 4
  4. char name[10]; // 12 4字节对齐
  5. };
sizeof    = 16


  1. struct STU
  2. {
  3. char id : 2; // 代表 id 是两个 bit 长
  4. };
sizeof = 1 


结构体里的类型可以  bit 位 存储
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct STU
  4. {
  5. char id : 2; //两个bit位 如果存4的话就会是0 如果存5的话就会是1
  6. };
  7. int main()
  8. {
  9. struct STU s1;
  10. s1.id = 4;
  11. printf("%d\n" , s1.id);
  12. }




对齐只针对字节,不会针对位来对齐
  1. struct STU
  2. {
  3. char id : 2;
  4. char name : 2;
  5. };
sizeof = 1


  1. struct STU
  2. {
  3. int id : 2;
  4. };
sizeof = 4


  1. struct STU
  2. {
  3. int id : 2;
  4. int age : 2;
  5. };
sizeof = 4


结构体之前的嵌套:
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct A
  4. {
  5. int i;
  6. char c;
  7. };
  8. struct B
  9. {
  10. int i;
  11. struct A a;
  12. };
  13. int main()
  14. {
  15. printf("%d\n" , sizeof(struct B));
  16. }
sizeof = 12



结构体之间的赋值:

结构体之间的赋值   原理就是内存的拷贝。
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct STU
  4. {
  5. char name[1024];
  6. };
  7. int main()
  8. {
  9. struct STU s1 = { "liuwei" };
  10. struct STU s2;
  11. s2 = s1; // memcpy( &s2 , &s1 , sizeof(s1)); 和这句话效果一样
  12. printf("%s\n",s2.name);
  13. }




结构体中 有指针的赋值:

如果是常量字符串,改变一个结构体的值,不会影响另外一个,因为内存中的地址不一样
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct STU
  4. {
  5. char *name;
  6. };
  7. int main()
  8. {
  9. struct STU s1 = { "liuwei" };
  10. struct STU s2;
  11. s2 = s1;
  12. s1.name = "xuanyuan";
  13. printf("%s\n",s2.name);
  14. }


但如果是在堆上开辟的新内存,那么复制的只是那个地址,指向的是同一块内存。如果改变了一个值,另外一个也会改变。
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. struct STU
  5. {
  6. char *name;
  7. };
  8. int main()
  9. {
  10. struct STU s1 , s2;
  11. s1.name = malloc(10);
  12. strcpy(s1.name , "liuwei");
  13. s2 = s1;
  14. strcpy(s1.name , "xuanyuan");
  15. printf("%s\n",s2.name);
  16. free(s1.name);
  17. }




 函数体返回结构体,然后赋值其实是内存拷贝      注意这个大坑
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct str
  4. {
  5. char buf[1024];
  6. };
  7. struct str get_str()
  8. {
  9. struct str s;
  10. strcpy( s.buf , "hello world");
  11. return s;
  12. }
  13. int main()
  14. {
  15. struct str tmp = get_str(); //返回的是一个结构体变量,结构体变量之间的赋值,是内存拷贝
  16. printf("%s\n" , tmp.buf);
  17. return 0;
  18. }



注意其他类型变量与结构体之间的区别         
  1. #include <stdio.h>
  2. #include <string.h>
  3. char *get_str()
  4. {
  5. char buf[100];
  6. strcpy( buf , "hello world" );
  7. return buf;
  8. }
  9. int main()
  10. {
  11. printf("%s\n" , get_str() ); //输出乱码,因为buf的地址已经被函数释放了
  12. return 0;
  13. }


在退出get_str函数的时候,内存释放,输出乱码。




如果函数实在要返回结构体,就返回结构体指针把          
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. struct str
  5. {
  6. char buf[1024];
  7. };
  8. struct str *get_str()
  9. {
  10. struct str *s = malloc(sizeof( struct str ));
  11. strcpy( s->buf , "hello world");
  12. return s;
  13. }
  14. int main()
  15. {
  16. struct str *tmp = get_str();
  17. printf("%s\n" , tmp->buf);
  18. free(tmp);
  19. return 0;
  20. }



返回结构体指针的一种错误方法
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct str
  4. {
  5. char buf[1024];
  6. };
  7. struct str *get_str()
  8. {
  9. struct str s;
  10. strcpy( s.buf , "hello world");
  11. return &s; //虽然返回的是结构体的地址,但是结构体的内存是在栈上,函数结束被释放
  12. }
  13. int main()
  14. {
  15. struct str *tmp = get_str();
  16. printf("%s\n" , tmp->buf);
  17. return 0;
  18. }



枚举的生长规律     是根据前一个值    再+1  
  1. #include <stdio.h>
  2. int main()
  3. {
  4. enum color{ red = 11 , yellow = 10 , blue};
  5. printf("%d\n",blue);
  6. return 0;
  7. }

需要注意的是枚举里面是以逗号分隔的,而不是以分号。



typedef的威力:
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. //这个函数是连接两个字符串
  5. const char *func( const char *str1 , const char *str2 )
  6. {
  7. char *p = malloc( strlen(str1) + strlen(str2) + 1 );
  8. strcpy( p , str1);
  9. strcat( p , str2);
  10. return p;
  11. }
  12. //如果要定义这个函数的 函数指针 如下
  13. const char *(*p)( const char *str1 , const char *str2 );
  14. int main()
  15. {
  16. p = func;
  17. char * s = p("hello","world");
  18. printf("%s\n",s);
  19. return 0;
  20. }


但是这样的函数指针看上去是不是很蛋疼呢?
  1. typedef const char *(*FUNC)( const char *str1 , const char *str2 );
可以用typedef 定义这个  函数指针 类型
方便以后使用


来自为知笔记(Wiz)


9.3 结构体 枚举 typedef