C语言 与结构体相关 函数 指针 数组

来源:互联网 发布:炫踪网络 融资 编辑:程序博客网 时间:2024/05/16 04:13

作者 : 万境绝尘

转载请注明出处 : http://www.hanshuliang.com/?post=30

.


结构体概述 : 结构体是 多个 变量的集合, 变量的类型可以不同;

-- 可进行的操作 : 结构体可以进行 拷贝 赋值操作, 可以作为 函数参数 和 函数返回值;


1. 结构体的基本使用


结构体声明 : struct 结构标记 {结构成员} 普通变量;

-- 结构体示例 : 

[cpp] view plaincopy
  1. struct student  
  2. {  
  3.     char *name;  
  4.     int age;  
  5. };  

-- 结构标记 : struct 后面的 student 是结构标记, 这个标记 可写 可不写, 其作用是 为结构命名, 结构标记可以代表 {} 中的声明的所有的成员变量;

-- 结构成员 : 在 {} 中定义的变量就是结构成员;

-- 普通变量 : 在声明结构体的时候后面可以加上若干普通变量, 相当于定义结构体变量;



结构体变量声明 : 可以在定义的时候声明变量, 也可以在定义完结构体使用 结构标记 声明变量;

-- 定义结构体时声明变量 : 这种声明变量的方式可以不用 结构标记, 变量名写在 花括号 后面, 用头号隔开;

[cpp] view plaincopy
  1. struct student  
  2. {  
  3.     char *name;  
  4.     int age;  
  5. } s1, s2, s3;  

-- 使用结构标记声明 : 结构标记 student 代表了花括号的声明, 是 结构体的简写, 可以使用结构标记代替花括号中的内容;

[cpp] view plaincopy
  1. struct student s4, s5, s6;  




结构体内存分配 : 结构体内存是在声明变量的时候分配的, 如果只声明了结构体, 没有声明对应变量, 那么不会分配内存;



结构体变量初始化 : 

-- 声明结构体的时候初始化 : struct student s1 = {"Tom", 12} ; 注意 初值表中必须时结构体对应类型的常量表达式;

-- 声明之后初始化 : 结构体变量名.成员名 可以访问结构体中的成员变量, s1.name = "Tom"; s2.age = 12;


结构体嵌套 : 结构体中的成员变量可以是 结构体变量;

[cpp] view plaincopy
  1. struct student  
  2. {  
  3.     char *name;  
  4.     int age;  
  5. } s1;  
  6.   
  7. struct class  
  8. {  
  9.     struct student s1;  
  10.     struct student s2;  
  11. } c1;  


结构体代码示例 : 

[cpp] view plaincopy
  1. /************************************************************************* 
  2.     > File Name: base_struct.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: 2014年03月24日 星期一 10时49分46秒 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>  
  9.   
  10. int main(int argc, char **argv)  
  11. {  
  12.     /* 
  13.      * 声明结构体 同时声明变量s1 
  14.      */  
  15.     struct student  
  16.     {  
  17.         char *name;  
  18.         int age;  
  19.     } s1;  
  20.   
  21.     /* 
  22.      * 结构体嵌套 
  23.      */  
  24.     struct class  
  25.     {  
  26.         struct student s1;  
  27.         struct student s2;  
  28.     } c1;  
  29.   
  30.     struct student s2 = {"Tom", 12};/*只有声明的时候才能对结构体初始化才能使用花括号赋值*/  
  31.     struct class c2 = {{"Jack", 13}, {"Pig", 15}};  
  32.     s1.name = "Hack";       /*变量声明后对结构体赋值只能一个一个赋值*/  
  33.     s1.age = 14;  
  34.     //s1 = {"fuck", 1};     /*只有在初始化的时候才能使用 花括号初始化结构体变量*/  
  35.     c1.s1.name = "CJ";  
  36.     c1.s1.age = 21;  
  37.     c1.s2.name = "KW";  
  38.     c1.s2.age = 22;  
  39.   
  40.     /*访问结构体中的变量, 使用 . 进行访问*/  
  41.   
  42.     printf("s1 : name = %s, age = %d \n", s1.name, s1.age);  
  43.     printf("s2 : name = %s, age = %d \n", s2.name, s2.age);  
  44.     printf("c1 : s1 : name = %s, age = %d ; s2 : name = %s, age = %d \n", c1.s1.name, c1.s1.age, c1.s1.name, c1.s2.age);  
  45.     printf("c2 : s1 : name = %s, age = %d ; s2 : name = %s, age = %d \n", c2.s1.name, c2.s1.age, c2.s1.name, c2.s2.age);  
  46.   
  47.     return 0;  
  48. }  

执行结果 : 

[plain] view plaincopy
  1. octopus@octopus-Vostro-270s:~/code/c/struct$ gcc base_struct.c   
  2. octopus@octopus-Vostro-270s:~/code/c/struct$ ./a.out   
  3. s1 : name = Hack, age = 14   
  4. s2 : name = Tom, age = 12   
  5. c1 : s1 : name = CJ, age = 21 ; s2 : name = CJ, age = 22   
  6. c2 : s1 : name = Jack, age = 13 ; s2 : name = Jack, age = 15   



2. 结构体与函数



结构体的合法操作 : 

-- 整体复制 : 结构体可以复制;

-- 整体赋值 : 声明结构体的时候可以整体赋值, 在其它情况下不可以;

-- & 取地址 : 使用 & 运算符获取 结构体地址;

-- 访问成员 : 使用 结构体变量名.成员变量名 可以访问成员变量;


函数传递结构体方法 : 

-- 传递结构体成员 : 将结构体拆开, 将其中的成员变量分别传入;

[cpp] view plaincopy
  1. struct class create_class(struct student s2, struct student s3)  
  2. {  
  3.     struct class c1 = {s2, s3};  
  4.     return c1;  
  5. }  

-- 传递结构体 :  将整个结构体当做参数传入, 这种情况和传递其它类型参数一样, 都是通过值传递的;

[cpp] view plaincopy
  1. struct class create_class(struct student s2, struct student s3)  
  2. {  
  3.     struct class c1 = {s2, s3};  
  4.     return c1;  
  5. }  

-- 传递结构体指针 : 传递结构体的指针, 访问形式如下;

[cpp] view plaincopy
  1. /* 
  2.  * 传入一个结构体指针 
  3.  * 通过指针访问结构体的方法 :  
  4.  *   (*结构体指针变量).成员变量 访问; 
  5.  *   结构体指针变量 -> 成员变量 访问; 
  6.  */  
  7. void printf_struct_pointer(struct student *s)  
  8. {  
  9.     printf("student : (*s).name = %s, (*s).age = %d \n", (*s).name, (*s).age);  
  10.     printf("student : s->name = %s, s->age = %d \n", s->name, s->age);  
  11. }  


结构体指针访问 :

-- 示例 : 定义一个结构体指针;

[cpp] view plaincopy
  1. struct student  
  2. {  
  3.     char *name;  
  4.     int age;  
  5. }*p;  

-- "." 和 "->"优先级 : 这两个运算符都是从左到右运算, 都是右结合; "." 和 "->" 优先级比 "*" , "++" 优先级要高; 这两个运算符 与 () [] 是四个优先级最高的运算符;

-- ++p->age 分析 : 是对结构体中的 age 进行自增操作;

-- *p->name 分析 : 获取 结构体中的 name 字符串的值(注意不是指针|地址);

-- *p++->name 分析 : 先获取 name 字符串的值, 再将p自增;



结构体函数示例 :

[cpp] view plaincopy
  1. /************************************************************************* 
  2.     > File Name: method_struct.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: 2014年03月24日 星期一 14时46分16秒 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>  
  9.   
  10. /*声明一个结构体类型, 其成员变量是普通变量*/  
  11. struct student  
  12. {  
  13.     char *name;  
  14.     int age;  
  15. };  
  16.   
  17. /*声明一个结构体类型, 其成员变量是结构体*/  
  18. struct class  
  19. {  
  20.     struct student s1;  
  21.     struct student s2;  
  22. };  
  23.   
  24. /* 
  25.  * 传递 2 个结构体的成员变量 
  26.  * 在函数中创建结构体并返回 
  27.  */  
  28. struct student create_student(char *name, int age)  
  29. {  
  30.     struct student s1 = {name, age};  
  31.     return s1;  
  32. }  
  33.   
  34. /* 
  35.  * 传递 2 个结构体变量 
  36.  */  
  37. struct class create_class(struct student s2, struct student s3)  
  38. {  
  39.     struct class c1 = {s2, s3};  
  40.     return c1;  
  41. }  
  42.   
  43. /* 
  44.  * 传入一个结构体指针 
  45.  * 通过指针访问结构体的方法 :  
  46.  *   (*结构体指针变量).成员变量 访问; 
  47.  *   结构体指针变量 -> 成员变量 访问; 
  48.  */  
  49. void printf_struct_pointer(struct student *s)  
  50. {  
  51.     printf("student : (*s).name = %s, (*s).age = %d \n", (*s).name, (*s).age);  
  52.     printf("student : s->name = %s, s->age = %d \n", s->name, s->age);  
  53. }  
  54.   
  55. int main(int argc, char **argv)  
  56. {  
  57.     /*使用函数获取一个结构体, 传入结构体的值*/  
  58.     struct student s1 = create_student("Tom", 11);  
  59.     printf("student : name = %s, age = %d \n", s1.name, s1.age);  
  60.   
  61.     /*创建一个成员变量是结构体的结构体, 并打印结构体数据*/  
  62.     struct class c1 = create_class(create_student("Jack", 12), create_student("CJ", 13));  
  63.     printf("c1 : s1 : name = %s, age = %d ; s2 : name = %s, age = %d \n", c1.s1.name, c1.s1.age, c1.s2.name, c1.s2.age);  
  64.       
  65.     /*声明结构体指针*/  
  66.     struct student *p = &s1;  
  67.     printf_struct_pointer(p);  
  68.     return 0;  
  69. }  

执行结果 : 

[plain] view plaincopy
  1. octopus@octopus-Vostro-270s:~/code/c/struct$ gcc method_struct.c   
  2. octopus@octopus-Vostro-270s:~/code/c/struct$ ./a.out   
  3. student : name = Tom, age = 11   
  4. c1 : s1 : name = Jack, age = 12 ; s2 : name = CJ, age = 13   
  5. student : (*s).name = Tom, (*s).age = 11   
  6. student : s->name = Tom, s->age = 11   


3. 结构体数组



(1) 结构体数组声明初始化



声明结构体数组 : 

-- 声明结构体的时候声明结构体数组 : 格式为 : struct 结构标记 {} 数组名[]; 

-- 使用结构标记声明结构体数组 : 格式为 : struct 结构标记 数组名[];



结构体数组声明初始化 : 

-- 逐个元素初始化 : 数组名[] = {{结构体1}, {结构体2}};

-- 总体初始化 : 数组名[] = {常量1, 常量2 ...}; 


结构体初始化 : 

[cpp] view plaincopy
  1. /************************************************************************* 
  2.     > File Name: array_struct.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: 2014年03月24日 星期一 16时40分15秒 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>  
  9.   
  10. /* 
  11.  * 声明结构体  
  12.  * 同时也声明结构体类型数组 
  13.  * 为数组初始化 
  14.  * 直接将每个结构体成员的值依次列出即可 
  15.  */  
  16. struct student  
  17. {  
  18.     char *name;  
  19.     int age;  
  20. } team1[] =   
  21. {  
  22.     "Tom", 12,  
  23.     "Jack", 13  
  24. };  
  25.   
  26. int main(int argc, char **argv)  
  27. {  
  28.     int i;  
  29.     /*将每个结构体初始化, 赋值, 每个结构体初始化内容使用 花括号括起来*/  
  30.     struct student team2[] = {{"CJ", 34}, {"KI", 32}};  
  31.     for(i = 0; i < 2; i++)  
  32.     {  
  33.         printf("team1 : team1[i].name = %s, team1[i].age = %d \n", team1[i].name, team1[i].age);  
  34.     }  
  35.   
  36.     for(i = 0; i < 2; i++)  
  37.     {  
  38.         printf("team2 : team2[i].name = %s, team2[i].age = %d \n", team2[i].name, team2[i].age);  
  39.     }  
  40.       
  41.     return 0;  
  42. }  

执行结果 : 

[plain] view plaincopy
  1. octopus@octopus-Vostro-270s:~/code/c/struct$ gcc array_struct.c   
  2. octopus@octopus-Vostro-270s:~/code/c/struct$ ./a.out   
  3. team1 : team1[i].name = Tom, team1[i].age = 12   
  4. team1 : team1[i].name = Jack, team1[i].age = 13   
  5. team2 : team2[i].name = CJ, team2[i].age = 34   
  6. team2 : team2[i].name = KI, team2[i].age = 32   


(2) 结构体数组示例程序


需求 : 实现一个统计 C 语言关键字出现次数;


代码 : 

[cpp] view plaincopy
  1. /************************************************************************* 
  2.     > File Name: word_count.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: 2014年03月24日 星期一 17时12分32秒 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>  
  9. #include<ctype.h>  
  10. #include<string.h>  
  11.   
  12. #define MAXWORD 10  
  13.   
  14. /* 
  15.  * 定义结构体类型 key  
  16.  * 该类型结构体中存储一个 字符串(关键字) 和 int 数据(关键字出现次数) 
  17.  * 同时声明一个结构体数组 
  18.  * 对结构体数组进行初始化 
  19.  * 
  20.  * 
  21.  */  
  22. struct key  
  23. {  
  24.         char *word;  
  25.         int count;  
  26. }key_count[] =   
  27. {  
  28.         "auto", 0,  
  29.         "break", 0,  
  30.         "case", 0,  
  31.         "char", 0,  
  32.         "const", 0,  
  33.         "continue", 0,  
  34.         "default", 0,  
  35.         "void", 0,  
  36.         "volatitle", 0,  
  37.         "while", 0  
  38. };  
  39.   
  40. int main(int argc, char **argv)  
  41. {  
  42.         int n;  
  43.         char word[MAXWORD];  
  44.   
  45.         /*循环接收字符串, 如果字符串与结构体数组中匹配, 结构体的count ++*/  
  46.         while(getword(word, MAXWORD) != EOF)  
  47.                 if(isalpha(word[0]))  
  48.                         if((n = binsearch(word, key_count, 10)) >= 0)  
  49.                                 key_count[n].count++;  
  50.   
  51.         /*打印大于0的关键字 及 个数*/  
  52.         for (n = 0; n < 10; n ++)  
  53.                 if(key_count[n].count > 0)  
  54.                         printf("%2d %s\n", key_count[n].count, key_count[n].word);  
  55.   
  56.         return 0;  
  57. }  
  58.   
  59. /*  
  60.  * 重要api解析 : 
  61.  *  int getc(FILE *stream) 从标准输入流中读取字符 
  62.  *  int ungetc(int c, FILE *stream) 将字符退回到标准输入流中 
  63.  *  int isspace(int c) 判断字符是否是 空格 '\f' '\r' '\n' '\t' '\v' 
  64.  *  int isalpha(int c) 判断是否是字母 
  65.  */  
  66. int getword(char *word, int lim)  
  67. {  
  68.         int c, getc(FILE*), ungetc(intFILE*);  
  69.         char *wp = word;  
  70.   
  71.         /*过滤空格, 如果输入的不是 空, 就继续向下执行*/  
  72.         while(isspace(c = getc(stdin)));  
  73.   
  74.         /*如果输入的不是结束符, 那么 wp指针, 先取值, 之后地址自增*/  
  75.         if(c != EOF)  
  76.                 *wp++ = c;  
  77.   
  78.         /*如果输入的不是字母, 直接返回, 关键字里面没有数字开头的*/  
  79.         if(!isalpha(c))  
  80.         {  
  81.                 *wp = '\0';  
  82.                 return c;  
  83.         }  
  84.   
  85.         /* 
  86.          * 循环条件 a. 接收的最大字符个数 lim, 每读取一个字符, 该变量自减  
  87.          * 当该变量自减为0时停止循环接收字符串 
  88.          * 循环条件 b. 当读取到的字符 不是 字母 或者数字的时候, 停止循环 
  89.          */  
  90.         for(; --lim > 0; wp++)  
  91.         {  
  92.                 if(!isalnum(*wp = getc(stdin)))  
  93.                 {  
  94.                         ungetc(*wp, stdin);  
  95.                         break;  
  96.                 }  
  97.         }  
  98.   
  99.         *wp = '\0';  
  100.         return word[0];  
  101. }  
  102.   
  103. /* 
  104.  * 参数解析 : word 是要查找的字符串 tab 字符串数组 n 字符串大小 
  105.  */  
  106. int binsearch(char *word, struct key tab[], int n)  
  107. {  
  108.         /* 
  109.          * cond 判断 查找的字符串 是在mid 坐标之前 (<0) 之后(>0) 或者就是mid坐标 
  110.          *  
  111.          * 如果查找的不是正好中间的变量符合, 就返回 -1 失败 
  112.          */  
  113.         int cond, low, high, mid;  
  114.   
  115.         low = 0;  
  116.         high = n - 1;  
  117.         /* 
  118.          * 要找的值的下标在low 和 high之间 
  119.          * mid 是 low 和 high 的中值 
  120.          * 如果 word 小于中值下标 将比较范围 缩小 
  121.          */  
  122.         while(low <= high)  
  123.         {  
  124.                 mid = (low + high) / 2;  
  125.                 if((cond = strcmp(word, tab[mid].word)) < 0)  
  126.                         high = mid - 1;  
  127.                 else if(cond > 0)  
  128.                         low = mid + 1;  
  129.                 else  
  130.                         return mid;  
  131.         }  
  132.         return -1;  
  133. }  

 

执行结果 : 

[plain] view plaincopy
  1. [root@ip28 struct]# gcc word_count.c   
  2. [root@ip28 struct]# ./a.out   
  3. auto  
  4. break  
  5. break  
  6. char  
  7.  1 auto  
  8.  2 break  
  9.  1 char  


宏定义方法 : 获取结构体数组大小;

-- sizeof 方法 : sizeof (对象) | sizeof (类型名称) 可以获取对象 或者 类型占用的存储空间, 其返回值是 size_t 类型的, 定义在stddef.h 头文件中;

-- 使用类型测量 : 

[cpp] view plaincopy
  1. #define KEYS (sizeof(key_count) / sizeof(struct key))  
-- 使用对象测量 : 

[cpp] view plaincopy
  1. #define KEYS (sizeof(key_count) / sizeof(struct key_count[0])  



4. 指向结构体指针



(1) 使用指针方式实现上面的关键字统计程序 


使用指针进行二分查找 : 

-- 使用下标找中值 : 在之前找中值时通过 mid = (low + high)方法, 这样做可行是因为 low 从0开始的;

-- 如果是指针情况 : mid low high 都是指针, 那么就不能使用上面的那种方法了, 使用 mid = low + (high - low) / 2;.

-- 指针操作情况的 high 和 low : 其中 low 是首元素的 首地址, high 是 尾元素的尾地址, 只有这样 它们的差的 0.5 倍才是准确的中值的首地址;


指针指向数组注意点 : 不要生成非法的指针, 指针不能指向数组之外的元素;

-- &key_count[-1] : 这个指针时非法的;

-- &key_count[n] : 对数组的最后一个元素后面的第一个元素进行 & 运算时合法的, 其它操作都是非法的;


示例程序 : 

[cpp] view plaincopy
  1. /************************************************************************* 
  2.     > File Name: pointer_struct.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: Tue 25 Mar 2014 12:31:08 AM CST 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>  
  9. #include<ctype.h>  
  10. #include<string.h>  
  11.   
  12. #define MAXWORD 20  
  13. /*计算结构体数组的大小*/  
  14. #define KEYS (int)(sizeof(key_count) / sizeof(struct key))  
  15.   
  16. struct key   
  17. {  
  18.     char *word;  
  19.     int count;  
  20. } key_count[] =   
  21. {  
  22.     "auto", 0,  
  23.     "break", 0,  
  24.     "case", 0,  
  25.     "char", 0,  
  26.     "const", 0  
  27. };  
  28.   
  29. int getword(char *, int);  
  30. struct key *binsearch(char*, struct key*, int);  
  31.   
  32. int main(int argc, char **argv)  
  33. {  
  34.     char word[MAXWORD];  
  35.     struct key *p; /*存放查找方法返回的结构体指针, 该指针指向数组中查找到元素的下标*/  
  36.   
  37.     while(getword(word, MAXWORD) != EOF)  
  38.         if(isalpha(word[0]))  
  39.             if((p = binsearch(word, key_count, KEYS)) != NULL)  
  40.                 p->count++;  
  41.       
  42.     for(p = key_count; p < key_count + KEYS; p++)  
  43.         if(p->count > 0)  
  44.             printf("%2d %s \n", p->count, p->word);  
  45.   
  46.     return 0;  
  47. }  
  48.   
  49. /* 
  50.  * 没有循环控制变量的 for 循环, 在内部通过条件 break 
  51.  */  
  52. int getword(char *word, int max)  
  53. {  
  54.     int c, getc(FILE*), ungetc(intFILE*);  
  55.     char *wp = word;  
  56.   
  57.     /*处理第一个字符, 第一个字符不是 空 不是 EOF 再进行下面的操作*/  
  58.     while(isspace(c = getc(stdin)));  
  59.     if(c != EOF)  
  60.         *wp++ = c;  
  61.     if(!isalpha(c))  
  62.     {  
  63.         *wp = '\0';  
  64.         return c;  
  65.     }  
  66.   
  67.     /*循环接收字符串, 字符串接收到非标识符 或者 到达个数上限停止循环*/  
  68.     for(; --max > 0; wp++)  
  69.         if(!isalnum(*wp = getc(stdin)))  
  70.         {  
  71.             ungetc(*wp, stdin);  
  72.             break;  
  73.         }  
  74.     *wp = '\0';  
  75.     return word[0];  
  76. }  
  77.   
  78. /* 
  79.  * 注意点 :  
  80.  *   取两个地址的中值 : 一个数组n个元素, 其中值计算 是由 首元素的首地址 和 尾元素的尾地址计算的 
  81.  *   二分查找 :  
  82.  *     如果要把区间前移, 那么就需要将尾地址设置为 中间元素前一个元素的尾地址, 即中间元素的首地址 
  83.  *     如果要把区间后移, 那么就需要将首地址设置为 中间元素后一个元素的首地址, 即中间元素 + 1 的地址 
  84.  * 
  85.  * 指向结构体数组的指针 :  
  86.  *   struct key tab * 是指向结构体数组指针, 该指针可以操作结构体数组 
  87.  */  
  88. struct key *binsearch(char *word, struct key *tab, int n)  
  89. {  
  90.     int cond;  
  91.     struct key *low = &tab[0];  /*0元素的首地址*/  
  92.     struct key *high = &tab[n]; /*尾元素的尾地址*/  
  93.     struct key *mid;  
  94.   
  95.     while(low < high)  
  96.     {  
  97.         /*计算中间值的地址*/  
  98.         mid = low + (high - low) / 2;  
  99.         if((cond = strcmp(word, mid->word)) < 0)  
  100.             high = mid; /*mid 是 中间元素前一个元素的尾地址*/  
  101.         else if(cond > 0)  
  102.             low = mid + 1; /*这里low要成为mid后一个元素的首地址*/  
  103.         else  
  104.             return mid;  
  105.     }  
  106.     return NULL;  
  107. }  

执行结果 : 

[plain] view plaincopy
  1. octopus@octopus-Vostro-270s:~/code/c/struct$ gcc pointer_struct.c   
  2. octopus@octopus-Vostro-270s:~/code/c/struct$ ./a.out   
  3. auto  
  4. case  
  5. auto  
  6. break  
  7.  2 auto   
  8.  1 break   
  9.  1 case   



(2) 结构体大小讨论 



结构体数组指针算术运算 : struct key *p = word_count; 指针 p 指向 结构体数组, 如果 p + 1 , 结果是 p 地址 加上 结构体所占内存大小;


结构体大小 : 结构体的大小不是完全等于各个成员的长度之和, 对象之间有对齐要求;

-- 空穴 : 对象间对齐, 会产生空穴, 占有空间, 但是不存储数据;


示例 : 结构体中由一个 char 和 int , 占用的空间却是 8个字节, 它们的和是 5个字节;

[cpp] view plaincopy
  1. /************************************************************************* 
  2.     > File Name: memory_struct.c 
  3.     > Author: octopus 
  4.     > Mail: octopus_work.163.com  
  5.     > Created Time: 2014年03月25日 星期二 12时55分45秒 
  6.  ************************************************************************/  
  7.   
  8. #include<stdio.h>  
  9.   
  10. struct word  
  11. {  
  12.     char c;  
  13.     int i;  
  14. };  
  15.   
  16. int main(int argc, char **argv)  
  17. {  
  18.     printf("sizeof(struct word) = %d \n"sizeof(struct word));  
  19.     return 0;  
  20. }  

执行结果 : 

[plain] view plaincopy
  1. octopus@octopus-Vostro-270s:~/code/c/struct$ gcc memory_struct.c   
  2. octopus@octopus-Vostro-270s:~/code/c/struct$ ./a.out   
  3. sizeof(word) = 8   




3、用typedef来简化结构体的写法

typedefstruct {

   int i,j;

}Node;

>>相当于把红色代码该名为Node了。以前需要这样声明"struct node n1;",现在只需要"Node n1;"

>>这段代码中,如果没有typedef,代码的意思是"声明了一个匿名结构体变量"!注意区别。

4、在结构体中声明结构体变量

typedef struct {

   int i,j;

   Node n1;

}Node;

>>这段代码是错误的!

>>错误1:直接在结构体中声明另外一个结构体,会出现死循环,如A包括B,B又包括A,A又包括B……使得编译器无法知道结构体的空间大小,因此,无法通过编译!

>>错误2:typedef还没有将结构体命名为Node,你就在结构体中使用了Node,显然,编译器此时还不知到Node是什么!所以,无法通过编译!

>>正确的使用方法如下:

typedef struct node{

   int i,j;

   struct node *n1;

}Node;

1、声明一个变量后的默认值

typedef struct {

   char *p;

   int i;

   char ch[256];

}mystr;

mystr str;//声明一个变量,此时已为之分配了空间!

4、动态生成结构体变量

mystr * pstr = (mystr*)malloc(sizeof(mystr));

pstr->p = "abc";

>>注意,如果是动态生成的结构体变量(用到了malloc),则必须在丢弃该变量前将他的内存空间释放掉(用free)。

>>如果结构体内部也存在动态生成的对象,在释放结构体之前要先释放掉其内部的内存空间,如下

pstr->p = (char*)malloc(sizeof(char)*256);

free(pstr->p);

free(pstr);


0 0
原创粉丝点击