1、结构体:用户自己建立不同数据类型组成的组合型的数据结构。
struct student
{
成员列表
};
struct student student1;
// struct 为声明结构体类型的关键字,student为结构体名
// struct student 为一个结构体类型
// student1 为 struct student 类型的变量
或者在定义结构体类型的同时定义结构体变量:
struct student
{
成员列表
}student1,stuednt2;
比较 struct 和 typedef struct:
typedef struct Student //也可以写成typedef struct
{
int a;
}Stu;
typedef 本质是对已有的类型进行重命名,对比 typedef int INT32,所以在这里Stu 等同于 struct Student。这两个都代表相同的数据类型,就可以用Stu代表struct Student结构体类型,所以如果要定义结构体变量,直接Stu student1即可。(Stu 用来定义变量,Stu 是类型而不是变量)
但是对于
struct student
{
成员列表
};
如果我们要定义一个结构体变量就必须 struct student student1这样才算定义了一个结构体变量,因为struct student 才是结构体类型
空结构体:在 vs2015 里面不允许空结构体的存在,但是在 gcc 编译器把空结构体的大小定义为0,这是个灰色地带。
2、柔型数组
— 柔型数组即数组大小待定的数组
— C语言中可以由 结构体产生柔型数组
— C语言中结构体的最后一个元素是大小未知的数组
— 柔型数组所占用的字节大小仅仅和长度的类型有关
好处:动态决定数组的长度
#include <stdio.h>
struct SoftArray
{
int len;
int array[];
};
int main()
{
printf("%d\n", sizeof(struct SoftArray)); //4,表明柔型数组结构体大小只有4个字节
return 0;
}
基本格式:
struct SoftArray
{
int len;
int array[];
};
...
struct SoftArray* sa = NULL;
sa = (struct SoftArray* )malloc(sizeof(struct SoftArray)+sizeof(int)*5);
sa->len = 5;
- 为什么指向动态内存的指针类型为结构体指针类型?
因为我们可以通过这个指针来给结构体里面的长度赋值。
实例程序:
#include <stdio.h>
#include <malloc.h>
struct SoftArray
{
int len;
int array[];
};
struct SoftArray* creat_soft_array(int length)
{
struct SoftArray* ret = NULL;
if(length > 0)
{
ret = (struct SoftArray*)malloc(sizeof(struct SoftArray) + sizeof(int) * length);
if(ret != NULL)
{
ret->len = length;
}
}
return ret;
}
void free_soft_array(struct SoftArray* sa)
{
free(sa);
}
void func(struct SoftArray* sa)
{
int i = 0;
if (NULL != sa)
{
for (int i = 0; i < sa->len; i++)
{
sa->array[i] = i + 1;
}
}
}
int main()
{
int i = 0;
struct SoftArray *sa = creat_soft_array(10);
func(sa);
for (i = 0; i < sa->len; i++)
{
printf("%d\n", sa->array[i]);
}
free_soft_array(sa);
return 0;
}
3、C语言中的联合体 union
联合体里面可以定义多个成员变量,在任何时刻,只有一个成员变量有效。union是只分配最大成员的空间,而且所有的成员共享这个空间.
比如说空间里面已经有一个 int 值,你一个 char 的只能是里面一个字节的那个值。
#include <stdio.h>
struct A
{
int a;
int b;
int c;
};
union B
{
int a;
int b;
int c;
};
int main()
{
printf("%d\n", sizeof(struct A)); // 12
printf("%d\n", sizeof(union B)); // 4 3个int值共享这4个字节
return 0;
}
union的注意事项:union的使用受系统大小端的影响,我们一般的电脑系统都是小端系统,union 和 struct 差不多,就是意义不同。
在小端系统里,1被存储在低地址上面;
在大端系统里,1被存储在高地址上面。
小端模式,低地址存储低位数据;大端模式,低地址存储高位数据。
例题:
#include <stdio.h>
union A
{
int i;
char c[2];
}a;
int main()
{
a.c[0] = 10;
a.c[1] = 1;
printf("i = %d\n",a.i);
return 0;
}
分析:10 == 0000 1010;1 ==0000 0001
在小端模式 0000 0001 0000 1010,这样就是低存低位,所以a.i = 266
在大端模式 0000 1010 0000 0001 0000 0000… 0000 0000,这样就是低存高位
例题翻转:
#include <stdio.h>
union A
{
int i;
char c[2];
}a;
int main()
{
a.i = 299;
printf("a.c[0] = %d\n", a.c[0]);
printf("a.c[1] = %d\n", a.c[1]);
return 0;
}
分析:
先已知a.i = 299,也就是256+43,可以清楚的知道,a.c[0] = 43,a.c[1] = 1
如何判别大小端:
#include <stdio.h>
int system_mode()
{
union SM
{
char c;
int i;
}sm;
sm.i = 1;
return sm.c;
}
int main()
{
if (1 == system_mode())
{
printf("this is 小端 mode\n");
}
else
{
printf("this is 大端 mode\n");
}
return 0;
}
特殊情况:
int system_mode()
{
union A
{
int i;
char c;
}a;
a.c = 1;
printf("%d\n", a.i);
return a.i;
}
原因在于:我初始化了小的内存,但是我无法保证 int 里面的其余3个字节都是空的。导致出现得出的结果不是1而出现是大端系统的原因,所以最好初始化大的内存 = 1。