论结构体
结构体是一个典型的从工程中诞生的封装结构,是需求选择了结构体,而不是结构体创造的需求。
1. 结构体是什么
维基百科中结构体的介绍如下:
在C语言中,结构体(struct)指的是一种数据结构,是C语言中复合数据类型(aggregate data type)的一类。
用通俗的语言概括就是把基本的数据类型按需组合,所构成的复合的数据类型。
2. 结构体有什么用
C语言诞生之初,并没有struct
结构体这玩意,遇到了多种数据类型耦合起来的复合数据类型,只能开多个类型的数组,并且设法进行管理。无疑既不优雅,又不便于理解,于是结构体诞生了。
工程师们喜欢层层封装,让代码抽象得具体,或者说具体的抽象,而结构体正是最典型的封装之一。对于一个大的工程而言,基本的数据类型无疑是不充分的,无法适应所有需求;而结构体的出现,以其灵活和强大瞬间给了这些问题一个解决方案。
我们可以用结构体组合多种变量去描述复杂的物体;我们可以把一组有关联的数据打包起来,一起传入函数或者作为函数的返回值,而不用零散地处理数据。
譬如你为商场超市编写一个商品管理程序,相比于写一堆数组去储存数据,如下的结构体显然更简洁:
|
|
C语言最初是作为UNIX操作系统的工具而存在的。在UNIX系统中,UNIX v3开发出了具有struct
功能的编译器,在随后的版本里立刻就开始使用。
可见结构体的诞生绝不是偶然,而是特定条件下的必然。其本质就是大型工程中,由程序员们对抽象和封装有着强烈需求,进而选择创造了结构体。是需求选择了结构体,而不是结构体创造的需求。
3. 使用结构体的注意事项
-
在C语言和C++中,结构体不完全一样,以下举例说明。
- C语言中定义和声明结构体:
1 2 3 4 5 6 7 8
struct goods //商品 { char name[20]; //商品名 float price; //单价 float weight; //重量 }; struct goods var_goods; //struct goods是类型名,var_goods是变量名
或者使用
typedef
关键字定义一个类型别名:1 2 3 4 5 6 7 8
typedef struct goods //商品 { char name[20]; //商品名 float price; //单价 float weight; //重量 }Good; Good var_goods; //“Good”是类型别名,var_goods是变量名,“Good”的使用和“int”类似
- C++中定义和声明结构体:
1 2 3 4 5 6 7 8
struct goods //商品 { char name[20]; //商品名 float price; //单价 float weight; //重量 }; goods var_goods; //goods是类型名,var_goods是变量名
C++中
struct
和class
本质都是类,所以使用类似,不需要加typedef
。 -
结构体中
->
和.
的异同 这里引用知乎——Lion Yang的概括:简单的说,就是一个快捷方式,一个语法糖。
照例用代码举例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#include <iostream> using namespace std; struct goods //商品 { char name[20]; //商品名 float price; //单价 float weight; //重量 }; int main(void) { goods s; //结构体 goods* p; //结构体指针 p = new goods; s.price = 10; p->price = 10; if ((&s)->price == (*p).price) { cout << "价格相等!" << endl; } delete p; }
可以看到我们用了
s.price
和p->price
进行赋值,也可以用(&s)->price
和(*p).price
进行读取。其本质并无太多差别,在内存中都是从结构体的基址进行偏移,在偏移后的内存地址赋值或取得所需数据。不过在使用上有些许区别:->
的左操作数是一个结构体指针变量;.
的左操作数是一个结构体变量。所以上面程序的结果是:
1
价格相等!
这两个操作符是历史遗留,当时编程大多是从机器的角度出发,编写的代码贴近机器逻辑而反人类直觉。假如机器会思考,
(*p).i
对它而言就像在数轴上从p开始数i个字;而对于p.i
它需要先找到p的位置再开始数。机器终究是为人类服务的,所以为了更直观地编程加入了->
操作符,使用->
可以让结构体指针(*p).i
简单地表示为p->i
,成为了折中的方案。