数据结构

本节来讨论c语言主要的数据结构,包括数组、结构体、共用体、枚举。首先从数组开始。

1、数组

数组为同一类型的基本数据的集合。我们知道,基本数据类型都占据一定的内存空间,基本数据类型的定义,实际上就是内存地址的分配过程,同样的,数组作为基本数据类型的集合,在创建时也必须进行内存的分配。以下都为正确的数组创建方法:

int num1[4]={0,1,2,3};  
int num2[4]={0,1};  
int num3[4]={[2]=2,[3]=3};  
int num4[]={0,1,2,3};  
int n=3;int num5[n];  
int num6[0]; 

错误的示例:

int num5[]; // 未明确范围  
int num6={0,1,2,3}; // 格式不对  
int num7[];num7={0,1,2,3}; // 整体赋值必须在定义时赋值  
int n=3;int num8[n]={0,1,2,3}; // 错误  
int num9[-1]; // 没有负数个  

特殊的数组:
a、字符数组(字符串)
在c语言中通过字符数组的方式表示字符串,字符串的结尾不是字符数组的结尾,而是字符数组中出现的第一个‘\0’。

char str[]={'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\0'};      
printf("%s\n", str);  

也可以采用下面的方式创建(这两者不等价):

char *str="Hello World!";  
printf("%s\n", str);  

b、多维数组
有的时候采用单一的数组也可能满足不了需求,这时候就需要用到多维数组,他的定义和普通的数组完全一样,只不过他的每一个元素本身都是一个数组。我们来看一下多维数组的存储方式:

int a[2][2]={{1,2},{1,2}};  
printf("a[0][0]: %p \n", &a[0][0]);  
printf("a[0][1]: %p \n", &a[0][1]);  
printf("a[1][0]: %p \n", &a[1][0]);  
printf("a[1][1]: %p \n", &a[1][1]);  

输出结果:

a[0][0]: 0x7fff5fbff8c0   
a[0][1]: 0x7fff5fbff8c4   
a[1][0]: 0x7fff5fbff8c8   
a[1][1]: 0x7fff5fbff8cc 

从上述结果中可以看出,多维数组和普通数组的存储方式完全一样,也是按次序摆放,只是调用的方式略有不同。

2、结构体

在数组中,所用元素的类型都必须是相同的,为了满足更个性化的需要,就出现了结构体,他是一种类似数组的结构,只不过其内部存储的变量不是单一的数据类型,可以由多种数据类型组成,甚至可以是某个函数。为了表示结构体的这种任意的特性,结构体需要开发者自己编写结构格式,典型结构体的格式定义如下(要放在主函数的前面):

struct student  {  
    int number;     //学号  
    int age;        //年龄  
    double height;  //身高  
    char name[8];     //姓名  
}; //注意分号  

该操作只是定义了一个名称为student的框架,并没有实际分配内存。
为了分配内存,我们需要对student结构体进行实例化:

struct student stu; // 获得student结构体实例stu  
// 地址及大小输出  
printf("stu            地址:%p 大小: %lu Byte \n", &stu, sizeof(stu));  
printf("stu.number     地址:%p 大小: %lu Byte \n", &stu.number, sizeof(stu.number));  
printf("stu.age        地址:%p 大小: %lu Byte \n", &stu.age, sizeof(stu.age));  
printf("stu.height     地址:%p 大小: %lu Byte \n", &stu.height, sizeof(stu.height));  
printf("stu.name       地址:%p 大小: %lu Byte \n", &stu.name, sizeof(stu.name)); 

在上面的方法中,我们通过点语法访问结构体实例的内部变量,并获取各变量的地址,输出结果:

stu            地址:0x7fff5fbff8c0 大小: 24 Byte   
stu.number     地址:0x7fff5fbff8c0 大小: 4 Byte   
stu.age        地址:0x7fff5fbff8c4 大小: 4 Byte   
stu.height     地址:0x7fff5fbff8c8 大小: 8 Byte   
stu.name       地址:0x7fff5fbff8d0 大小: 8 Byte 

可以看出,在结构体实例中,内存的分配是按照内部变量的次序依次排列的,结构体的地址为第一个变量的地址,这和前面的结论一致。

3、共用体

共用体和结构体的创建方法基本相同,所不同的是他的内部变量公用相同的存储单元。为什么要这样做呢?是因为并不是所有的硬件都有足够的内存供我们使用,在有些场合下,一个“结构体”的内部变量同时只用到一个,这时候使用共用体将大大节省内存开支。此外,在通信领域,有时候在接受数据时无法确定数据的类型,先把数据存储下来,然后再根据类型对应读取,举例如下:
创建共用体框架(同样要放在主函数前面):

union reciveData  {  
    int number;     // 数字  
    char character;  // 字符  
}; 

实例化及验证:

union reciveData data; // 实例化  
// 地址及大小输出  
printf("data                 地址:%p 大小: %lu Byte \n", &data, sizeof(data));  
printf("data.number          地址:%p 大小: %lu Byte \n", &data.number, sizeof(data.number));  
printf("data.character       地址:%p 大小: %lu Byte \n", &data.character, sizeof(data.character)); 

输出结果:

data                 地址:0x7fff5fbff8d8 大小: 4 Byte   
data.number          地址:0x7fff5fbff8d8 大小: 4 Byte   
data.character       地址:0x7fff5fbff8d8 大小: 1 Byte  

由输出结果可以看出,共用体实例的存储空间为共用体实例内部最大元素的尺寸,各元素的地址相同,都等于共用体的地址。

4、枚举

枚举是一种特殊的数据结构,他将某些固定的数值表示成有意义的标识符,以提高程序的可读性。
枚举和上面的结构体和共用体类似,也需要在主函数前面声明其框架,例如:

enum {spring, summer, autumn, winter} season; //不含类型标签,定义单一的变量  
enum color_led {red, green, blue}; //含类型标签,可定义多个变量  

这两个枚举分别定义了四季和LED灯的三种状态,不同的是,第一个例子中没有“框架名称”,直接声明了单一的枚举,其标识符为season。第二个例子中有“框架名称“color_led”,我们可以通过此名称创建多个相似的框架。注意,这里并没有分配空间!如果你尝试通过&指令输出地址的话,会报错!
第一个例子的输出:

printf("spring = %d\n", spring);  
printf("summer = %d\n", summer);  
printf("autumn = %d\n", autumn);  
printf("winter = %d\n", winter);

结果为:

spring = 0  
summer = 1  
autumn = 2  
winter = 3  

可见,这些标识符在真正运行的阶段还是以数字的形式进行流通,只是我们给他们换了一个叫发,方便了编程工作及思路的整理。顺便一提的是,我们可以在定义枚举的时候人为的改变这些默认值,方法如下:

enum {  
    spring,  
    summer = 2,  
    autumn,  
    winter
} season;  

此时,summer之后的数据根据summer依次递加,前面的保持不变,输出如下:

spring = 0  
summer = 2  
autumn = 3  
winter = 4 

5、总结

合理运用以上几种复杂数据类型,将使我们的程序变得完善和规范,同时便于我们思路的理清。务必弄清楚这几种数据的使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容

  • 原文链接:Collection Data Structures In Swift原文日期:2015/04/21 译...
    梁杰_numbbbbb阅读 4,948评论 2 14
  • 从数据到算法 数据与数据结构 任何问题解决方案都不可能脱离数据结构而单独存在。所谓数据类型就是一个值的集合和定义在...
    认真学计算机阅读 428评论 2 3
  • 9.3.3 快速排序   快速排序将原数组划分为两个子数组,第一个子数组中元素小于等于某个边界值,第二个子数组中的...
    RichardJieChen阅读 1,833评论 0 3
  • 1.IE的双边距BUG:块级元素float后设置横向margin,ie6显示的margin比设置的较大。 解决:加...
    不去解释阅读 613评论 0 3
  • 今天非常的忙碌,事情一件接着一件,在忙碌的状态下,发现只能利用碎片化的时间把笑来老师的文章读一遍,但可见囫...
    YY_8360阅读 153评论 0 0