天天看点

20170128C语言提升02_结构体和union和void上节回顾:enum:struct:union:void:

上节回顾:

typedef和define是有很大差别的,后者只是替换,在多个变量一起赋值的时候一定注意!

typedef char* PCHAR;
#define PINT int*
int main()
{
	PCHAR p1, p2;//这两个都是char*类型的
	char c1 = '1',c2 = '3';
	PINT p3, p4;//前面一个是int*,后面一个是int型的。宏定义只是简单的替换。
	int n1 = 1, n2 = 3;
	p1 = &c1; p2 = &c2;
	p3 = &n1; p4 = &n2;//后面这个会警告,说把int*转化为int了。
	return 0;
}
           

enum:

    枚举,完全的自定义类型,主要用于定义常量值,一些简单的常量可以使用define来定义,一个系列的常量用enum来定义比较好。enum经常和switch来搭配使用。

struct:

    结构体,可以将一些数据有效的规整到一块。结构体变量的申请前面必须要加上struct。或者也可以使用typedef。

typedef struct tagStudent
{
	int index;
	int no;
	char name[20];
}Student;
           

    后面的程序就可以使用Student来申请结构体变量。他仅仅是将typedef和定义结合在一起,与普通的typedef是一样的。访问结构体里面的每一个变量可以使用点号或者指针箭头来。但是一定要注意,如果数据有数组或类是的,不可以直接与常量数组(字符串等)相等,要深拷贝才可以。结构体里面最好还是不用指针。以防止出错。

    struct里面不可以有函数(纯C语言里面),但是C++里面是可以的,类似于class。

    一个结构体的大小不一定是其中所有元素的大小加起来的大小。例如当总共为31字节的时候,可就会是32字节,当不足4字节的时候,他会补全。他只会是4的整数倍。如果里面没有任何元素,编译器会报错,是未定义的行为。

    结构体里面的数组大小必须要是可能出现最大的数据的大小以上。这样可能导致浪费空间,但又不可以动态分配数组的大小,解决方案是使用柔性数组。必须只能是一个且为最后一个为[],其他的必须有数字

#include <stdio.h>
typedef struct SoftArray
{
	int i;
	char c;
	int array[10];
//	int array1[];//这里会出错,error C2229: struct“SoftArray”有非法的大小为零的数组,这个不传递大小的只能在最后一个,且只能只有一个。
	int array1[10];
	int array2[];//他是不占空间的。他只能表示后面多的空间按什么形式和以什么名字来访问。
}SoftArray;
int main()
{
	printf("%d\n", sizeof(SoftArray));//会打印88
	return 0;
}
           

    柔性数组他会自动分配到最后的数据里面去,malloc申请的时候因该计算准确。动态分配数组示例:

#define  _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef struct tagSoftArray
{
	int len;
	int array[];//并没有定义他的大小,它的作用只是占位。
}SoftArray;
int main()
{
	int len = 0;
	printf("%d", sizeof(SoftArray));
	printf("请输入数组大小");
	scanf("%d", &len);
	SoftArray *sa = (void*)malloc(sizeof(SoftArray) + sizeof(int) * len);//除了SoftArray大小后之后全部是int的整数大小
	sa->array[10] = 1;//输入的长度小于11也不报错,但是超出范围,不安全。
	free(sa);//输入小于11的时候,这里释放会出错。释放后再使用这个,访问是没有问题的,但是指针已经变成野指针。
	return 0;
}
           

    上面sa的地址&sa和sa->array[]的地址是接近的,实际他是挨着分配的。习惯上总是将不再使用的指针设置成空指针否则如果用了这个指针可能导致错误很难找到。设置成空指针的话,就会触发空指针异常。

union:

    联合:struct里面每个元素都有自己的空间,union是共享空间。使用的一个空间。

    他的总大小是里面最大的一个的大小。现在一般用的不多,早期用的比较多。用的最多的地方是判断大小端。

大小端模式:

    内存低地址存放高位数据称为大端,反过来高地址存放数据高位称为小端。这两种存储方式会影响到我们读取的方式。生活中,人们更习惯大端模式。大端模式还是小端模式取决于硬件和系统,大端对于网络通讯很有优势。现在大部分机器都是小端机,即从尽量把数据存放在地位地址。

void:

    表示无,这个类型是无法使用的,它代表的是空,他经常用在无返回值和无参数。但是void*是可以使用的。void*代表的是他所指向的就是一块内存,具体里面有多大是不知道的。int*和char*等指针之间是不可以互相转换的,但是任何指针都可以无屏障地转化到void*,他是一个万能指针。可以提供一种数据抽象能力。但void*会导致的问题是到最后不知道最开始的是什么类型的了。

继续阅读