一、结构体的声明
#include<stdio.h>
int main() {
/* 第一种声明 */
struct person_information { /* 声明结构体的数据类型*/
char name[10];
int age;
char gender;
};
struct person_information Joe; /* 定义结构体变量 */
/* 第二种声明 */
struct person_information2 {
char name[10];
int age;
char gender;
} Joe1, Philip; // 从该处定义结构体变量
/* 第三种声明 */
struct {
char name[10];
int age;
char gender;
} Joe2, Philip2; // 不声明结构体名字直接声明
/* 第四种声明 */
typedef struct person_information3 { // 通过 typedef 简化结构体名字,person_information3 可省略
char name[10];
int age;
char gender;
} p_i;
p_i Joe3, Philip3; // 声明结构体变量
/* 第五种声明 */
// 如果结构体内定义指向本结构体类型空间的指针时,只能通过这种声明
typedef struct person_information4 {
char name[10];
int age;
char gender;
struct person_information3 * next; // 声明一个指向本结构体类型空间的指针
} p_i2;
}
二、结构体的长度
为了寻址方便,数据在内存中存储时一般以其本身数据类型的字节长度为基本单位对齐。 如:int型在内存中以 sizof(int) 字节对齐。而结构体中数据在存储时以其中字节最大长度最大的成员的字节数为基本单位对齐的。
#include<stdio.h>
int main() {
typedef struct information {
char a[3]; // 占3个字节
int b; // 占4个字节
char c; // 占1个字节
} v1;
struct {
int a2; // 占4个字节
double b2; // 占8个字节
} v2;
struct {
char a3[3]; // 占3个字节
char c3; // 占1个字节
int b3; // 占4个字节
} v3;
printf("%d", sizeof(v1)); // 12个字节 4 + 4 + 4
printf("%d", sizeof(v2)); // 16个字节 8 + 8
printf("%d", sizeof(v3)); // 8个字节 4 + 4
}
三、结构体成员变量的赋值
#include<stdio.h>
int main() {
typedef struct student {
char name[3];
int age;
int sex;
} stu;
stu joe;
// joe.name = {'J', 'o', 'e'}; 对于结构体内的数组,只能在函数体内进行赋值,在函数体外只能初始化
joe.age = 12;
joe.sex = 1;
stu philip = {{'j', 'o', 'e'}, 12, 1};
stu jams = {"joe", 12, 1};
}
四、浅复制与深复制
#include <stdio.h>
int main () {
typedef struct _data {
int a;
int * p;
} data_t;
int x = 2;
data_t a = {12, &x};
data_t b = a; // 浅复制,将a内存内容按字节复制给b
// 如果结构体中含指针型成员的话,会存在安全隐患。如果a,b某个指针指向一块堆内存,很可能导致多次释放同一块堆内存。
}
// 深复制:如果结构体含有指针型成员,则先为该指针成员申请新的内存空间,再复制其指向的空间内容。复制后的结构体便得到一个独立的内存空间。
// 深复制分为复制非指针成员部分和复制指针成员部分。
/* 非指针成员的复制 */
b->m1 = a->m1;
b->m2 = a->m2;
/* 指针部分 */
b->m3 = (int *) malloc (sizeof(int));
if (NULL == b->m3) {
return false;
}
b->m3 = a->m3; // 深复制
free(b->m3); // 记得释放内存
b->m3 = NULL;
五、结构体数组
#include<stdio.h>
int main() {
typedef struct student {
char name[10];
int age;
char gender;
} stu;
stu boy1[2] = {
{"boya", 12, 'M'},
{"boyb", 12, 'M'}
};
// 第二种声明方法
struct {
char name[10];
int age;
char gender;
} boy2[2] = {
{"boyc", 12, 'M'},
{"boyd", 12, 'M'}
};
// 获取某一个元素类似 boy1[i].name
}
六、结构体指针
#include<stdio.h>
int main() {
typedef struct student {
int a;
int * b;
} stu;
int x = 2;
stu boy = {1, &x};
stu * p = &boy; // 指向结构体变量的指针
printf("%d", (*p).a); // 通过指针获取结构体的属性
printf("%d", p->a); // 功能同上
}
#include<stdio.h>
int main() {
typedef struct student {
int a;
int * b;
} stu;
stu * p = NULL;
p = (int *) malloc (sizeof(student)); // 申请student大小的空间
p->a ... 进行元素属性操作
...
}
#include<stdio.h>
int main() {
typedef struct student {
int a;
int * b;
} stu;
int x,y = 1;
stu boy1[2] = {
{1, &x},
{2, &y}
};
stu * p = boy1;
// (p++)->name 获取每个数组内元素的属性
}