struct 是一种把一些数据项组合在一起的数据结构。在Go,Rust这些新语言中都保留了结构体 struct 的概念,这是C的精华。
定义匿名结构体
例:学生信息定义为一个结构体,信息内容包括学生的姓名(string)、学号(long)、年龄(int)等,就可以声明如下:
struct {
char sName[];
long sNo;
int sAge;
};
定义结构体变量
结构体本质是一种数据类型,和C语言的内置内型(char,int,long ...)类似,我们可以用它来定义变量,如:
// 定义一个学生jack就可以这样:
struct {
char sName[];
long sNo;
int sAge;
} jack ; // 如还要再定义一个学生rose;
struct {
char sName[];
long sNo;
int sAge;
} rose;
定义结构体类型
我们就发现每次定义一个这样的结构体变量非常麻烦,每次都要将结构体类型声明完整写一遍,于是就引进了在struct关键字后面加上“结构标签”,例如上面的结构体就可声明为:
struct stuInfo{
char sName[];
long sNo;
int sAge;
};
定义变量:
struct stuInfo jack;
struct stuInfo rose;
以OOP的角度来看,struct stuInfo是一种"类型"。
使用typedef定义新类型
到这里就更有OOP的Class的味道了。
在使用 typedef 时,struct的定义可以直接使用匿名结构体,使用typedef定义新类型名:
typedef struct {
char a;
int b;
char c;
int d;
} DATA;
对于已经被定义名称的struct,可以通过typedef对类型增加名称。
例:将上面的struct stuInfo重新命一个名字,如叫sInfo:
typedef struct stuInfo sInfo;
定义变量:
sInfo jack;
sInfo rose;
sInfo就是一个"类型"。
将上面几步融合一起,就是我们通常所使用的定义结构体变量的方法:
先声明一个结构体:
typedef struct stuInfo{
char sName[];
long sNo;
int sAge;
} sInfo;
再定义变量:
sInfo jack, rose;
结构体赋值
struct中未被初始化的成员默认为0(指针类型的成员默认为NULL)。
顺序赋值
struct User oneUser = {, "Lucy", "/home/Lucy"};
乱序赋值
struct User oneUser = {
.name = "Lucy",
.id = ,
.home = "/home/Lucy"
};
还有一种乱序赋值,常出现在C++代码中,非常像JSON格式。
struct User oneUser = {
name:"Lucy",
id:,
home:"/home/Lucy"
};
嵌套类型
类型嵌套,可以使用typedef重定义的类型名,也可以使用struct 类型作为声明。
类型自嵌套,无法使用typedef重定义的类型名,只能直接使用struct类型作为声明。
例:如下代码是一个通用链表的struct。
typedef struct myNode {
void * data;
struct myNode *next;
} MyNode; typedef struct myList {
MyNode * first;
MyNode * last;
int count;
int (*equal)(void * a, void * b);
} MyList;
结构体内存对齐问题
先说结论:写结构体时,尽量将同类型的数据放在一起,这样会节省内存分配的空间。
看例子:
#include <stdio.h>
#include <stdlib.h> int main(void) { struct {
int age;
char firstName;
char secondName;
} xiaoming; struct {
char firstName;
int age;
char secondName;
} xiaohong; int mLen =sizeof(xiaoming);
int hLen =sizeof(xiaohong); printf ("%d %d\n",mLen, hLen);
return EXIT_SUCCESS;
}
输出: 8 12
为什么?这里暂时不研究了。引一篇博客:
《结构体字节对齐》 http://www.cnblogs.com/longlybits/articles/2385343.html