精华内容
下载资源
问答
  • 3.创建一个文件,将上面的数据顺序存储到文件; 4.查询第二个数据并输出; 5.在第二个数据后插入一个记录并输出整个数据; 6.删除第三个数据并输出整个数据; 第二组 7.创建一个文件,将上面的数据链式存储到文件...

    代码功能描述:

    1.创建一个结构体变量,包括5个成员(学号,姓名,性别);
    2.生成一个结构体数组,并输入5个记录数据;
    第一组
    3.创建一个文件,将上面的数据顺序存储到文件中;
    4.查询第二个数据并输出;
    5.在第二个数据后插入一个记录并输出整个数据;
    6.删除第三个数据并输出整个数据;
    第二组
    7.创建一个文件,将上面的数据链式存储到文件中;
    8.查询第3个数据并输出;
    9.在第二个数据后插入一个记录并输出整个数据;
    10.删除第4个数据并输出整个数据;

    代码:

    #include<stdio.h>
    #include<malloc.h>
    #define MaxSize 50
    struct student          //创建结构体变量
    {
    	char name[20];
    	char age[10];
    	char num[10];
    	char sex[10];
    	char clas[10];
    };
    typedef student ElemType;
    typedef struct {
    	ElemType date[MaxSize];
    	int length;
    }SqList;			//声明顺序表类型
    void CreatSqList(SqList*& L, ElemType a[], int n) {	//创建顺序表
    	L = (SqList*)malloc(sizeof(SqList));
    	for (int i = 0; i < n; i++)
    	{
    		L->date[i] = a[i];
    		L->length = n;
    	}
    }
    void DispSqList(SqList* L) {					//输出线性表
    	for (int i  = 0; i <L->length; i++)
    	{
    		fwrite(&L->date[i], sizeof(ElemType), 1, stdout);  //stdin表示屏幕的文件缓冲区
    		printf("\n");
    	}
    }
    void SaveSqInf(SqList* L) {			//向文件中存储学生信息
    	FILE* fp;
    	if (!(fp = fopen("studentsqlist", "wb")))	//打开文件,若无此文件则创建
    	{
    		printf("no open /n");
    		return;
    	}
    	for (int i = 0; i <	L->length;i++)
    	{
    		if (fwrite(&L->date[i], sizeof(ElemType), 1, fp) != 1) {	//数据块写入
    			printf("write error\n");
    			fclose(fp);
    		}
    	}
    }
    bool GetSqElem(SqList* L, int i, ElemType& e) {
    	if (i<1||i>L->length)
    	{
    		return false;
    	}
    	e = L->date[i - 1];
    	return true;
    }
    bool SqListInsert(SqList*& L,int i,ElemType e) {
    	int j;
    	if (i<1 || i>L->length+1 || L->length==MaxSize)
    	{
    		return	false;
    	}
    	i--;
    	for (j = L->length; j > i; j--) {
    		L->date[j] = L->date[j - 1];
    		L->date[i] = e;
    		L->length++;
    		return true;
    	}
    }
    bool SqListDelete(SqList*& L, int i, ElemType& e) {
    	int j;
    	if (i<1 || i>L->length + 1)
    	{
    		return false;
    	}
    	i--;
    	e = L->date[i];
    	for (j = i; j < L->length-1; j++) {
    		L->date[j] = L->date[j + 1];
    		L->length--;
    		return true;
    	}
    }
    /*--------------------------------*/
    typedef struct	LNode{                       
    	ElemType date;
    	struct LNode* next;
    }LinkNode;
    void CreatListF(LinkNode*& L, ElemType a[], int n) {           // 创建的链表是有头结点的。
    	LinkNode* s;
    	L = (LinkNode*)malloc(sizeof(LinkNode));
    	L->next = NULL;
    	for (int i = 0; i < n; i++)
    	{
    		s = (LinkNode*)malloc(sizeof(LinkNode));
    		s->date = a[i];
    		s->next = L->next;
    		L->next = s;
    	}
    }
    void DispLinkList(LinkNode* L) {
    	LinkNode* p = L->next;
    	while (p!=NULL)
    	{
    		fwrite(&p->date, sizeof(ElemType), 1, stdout);
    		p = p->next;
    	}
    	printf("\n");
    }
    bool SaveLinkList(LinkNode* L) {
    	LinkNode* j = L->next;
    	FILE* fp;
    	if (!(fp = fopen("studentlinklist", "wb")))	//打开文件,若无此文件则创建
    	{
    		printf("no open /n");
    		return false;
    	}
    	while (j!=NULL)
    	{
    		fwrite(&j->date, sizeof(j->date), 1, fp);
    		j = j->next;
    	}
    	return true;
    }
    bool GetLinkElem(LinkNode* L, int i, ElemType& e) {
    	int	j=0;
    	LinkNode* p = L;
    	if (i<=0)
    	{
    		return false;
    	}
    	while (j<i && p!=NULL)
    	{
    		j++;
    		p = p->next;
    	}
    	if (p==NULL)
    	{
    		return false;
    	}
    	else
    	{
    		e = p->date;
    		return true;
    	}
    }
    bool LinkListInsert(LinkNode*& L, int i, ElemType e) {
    	int j = 0;
    	LinkNode* p = L, * s;
    	if (i<=0)
    	{
    		return false;
    	}
    	while (j<i-1&&j!=NULL)
    	{
    		j++;
    		p = p->next;
    	}
    	if (p==NULL)
    	{
    		return false;
    	}
    	else
    	{
    		s = (LinkNode*)malloc(sizeof(LinkNode));
    		s->date = e;
    		s->next = p->next;
    		p->next = s;
    		return true;
    	}
    }
    bool LinkListDelete(LinkNode*& L, int i, ElemType& e) {
    	int j = 0;
    	LinkNode* p = L, * q;
    		if (i<=0)
    		{
    			return false;
    		}
    		while (j<i-1&&p!=NULL)
    		{
    			j++;
    			p = p->next;
    		}
    		if (p==NULL)
    		{
    			return false;
    		}
    		else
    		{
    			q = p->next;
    			if (q==NULL)
    			{
    				return false;
    			}
    			e = q->date;
    			p->next = q->next;
    			free(q);
    			return true;
    		}
    }
    /*------------------------------------*/
    int main() {
    	ElemType a[5];
    	SqList* S;
    	LinkNode* L;
    	int n = 5;
    	printf("please input information of students :\n");
    	printf("name age num sex class\n");
    	getchar();
    	for (int i = 0; i < 5; i++)
    	{
    		scanf("%s,%s,%s,%s,%s", &a[i].name, &a[i].age, &a[i].num,&a[i].sex,&a[i].clas);
    		getchar();
    	}
    	printf("Creat the SqList\n");
    		CreatSqList(S, a, n);
    		printf("input sqlist to file\n");
    		SaveSqInf(S);
    		printf("get 2th elem:   \n");
    		ElemType e;
    		GetSqElem(S, 3, e);
    		printf("elem :%s %s %s %s %s\n", e.name, e.age, e.name, e.sex, e.clas);
    		printf("insert elem: \n");
    		SqListInsert(S, 2, e);
    		DispSqList(S);
    		printf("\n");
    		printf("delete elem: \n");
    		SqListDelete(S, 3, e);
    		DispSqList(S);
    		printf("\n");
    	printf("Creat the LinkList\n");
    		CreatListF(L, a, n);
    		printf("input Linklist to file\n");
    		SaveLinkList(L);
    		printf("get 2th elem:   \n");
    		ElemType d;
    		GetLinkElem(L, 3, d);
    		printf("elem :%s %c %s %s %c\n", d.name, d.age, d.name, d.sex, d.clas);
    		printf("insert elem: \n");
    		LinkListInsert(L, 2, d);
    		DispLinkList(L);
    		printf("\n");
    		printf("delete elem: \n");
    		LinkListDelete(L, 3, d);
    		DispLinkList(L);
    		return 0;
    }
    

    补充

    1.文件创建的位置在你编译器创建项目所选的路径。
    2.fwrite 是数据块读写 用stdout相当于数据块printf;
    关于文件的一些内容可以看我的学习总结:
    https://blog.csdn.net/qlkdxxx/article/details/113323598
    3.文件的存储会出现乱码问题,c语言的文件相当难调,你要是为了应付作业
    代码没问题就可以了。不同的电脑,或者你读文件的软件不同显示也会不同,还有存储,编码,等等要考虑的。c语言的文件比较接近底层,相比较java等其他语言就比较难,不是有句话说 c语言是大佬玩的嘛。
    乱码的问题以我的能力还没能解决,你要是应付作业估计够用了,希望对你有帮助。

    总结或者前言吧:

    这个是我学数据结构时老师布置的作业,当初学的时候完全不编代码。等放假回了家翻回去学的。
    当时我学的时候交作业就直接厚着脸皮纯用别人的代码,对,连csdn都懒得看! 所以你上这儿来翻找已经比我强很多了。
    所以你刚学习编码能力比较弱不要灰心,时间比较忙就先应付过去。
    我们班上数据结构课上听得基本没有 ,是真的基本一两个 考试我也是最后一个礼拜狂刷网课不写代码过的。
    所以我的建议是 如果上课跟不上,你可以去b站找个网课看看,数据结构真的非常重要,从一开始你就看网课更上进度,后面你就会轻松很多。
    哈哈 我本身就是半吊子到说教开了,也算是对我自己的勉励吧,
    代码如果有错误也请指出来,希望可以一起进步!

    展开全文
  • NDK开发汇总 一 结构体 结构体: 一系列不同类型的数据的结合 ...实现一个双向链表,存储的是随机数据(int | char *)。增删改查。并且对双链表数据进行排序 typedef 就是别名,类似java代理,并没...

    NDK开发汇总

    一 结构体

    结构体: 一系列不同类型的数据的结合

    • 注意:类型!= 变量。 结构体名代表的只是结构体类型,没有内存空间。
    • 结构体中的成员可以单独使用
    • 结构体是C编程中一种用户自定义的数据类型,类似于Java的JavaBean

    1 定义结构体

    struct Studet {
    	char name[20];
    	int age;
    	char gender[10];
    	int classId;
    };
    //使用:struct Studet st;
    

    也可以定义全局,与方法中使用的结构体类型一致,作用域不同

    struct Studet {
    	char name[20];
    	int age;
    	char gender[10];
    	int classid;
    }Lucy;
    

    2 匿名结构体

    用一种特殊的结构体,没有结构体名称直接定义变量名:
    作用:不能再申请对应类型的变量,类似java的匿名内部类

    struct  {
    	char name[20];
    	int age;
    	int classid;
    } stu2,stu3;
    

    注意:

    • 类型不等于变量,结构体名代表的只是结构体类型,不会分配内存空间
    • 对结构体成员可以单独成员可以单独使用

    3 初始化

    1. 第一种初始化方式:
      struct关键字可以不要
    struct Student {
    	char name[20];
    	int age;
    } ;
    
    int test4() {
    	struct Student stu1 = { "lucy" ,20};
    	return 0;
    }
    
    1. 第二种初始化方式
    	struct Student stu2;
    	strcpy(stu2.name, "lucy");
    	stu2.age = 20;
    

    **注意:**数组的初始化用strcpy

    1. 第三种初始化方式
    struct Student {
    	char name[20];
    	int age;
    } Lucy = { "lucy", 20 }; 
    

    结构体中的成员可以单独使用

    struct Student stu2;
    	strcpy(stu2.name, "lucy");
    	stu2.age = 20;
    
    	printf("%s,%d\n", stu2.name, stu2.age);
    

    运行结果:lucy,20

    错误:

    错误	C4996	'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.	NDK_C	c:\users\pf0zybaj\source\repos\ndk_c\ndk_c\lsn04.cpp	32	
    
    

    属性->预处理-> 添加: _CRT_SECURE_NO_WARNINGS

    5 使用typedef定义

    //Student 相当于类名
    //student和a 可以不定义,表示结构变量,也就Student类型的变量
    struct Student
    {
    	char name[50];
    	int age;
    } student,a;
    //使用typedef定义
    typedef struct{
        char name[50];
        int age;
    } Student;
    

    当结构体需要内存过大,使用动态内存申请。结构体占用字节数和结构体内字段有关,指针占用内存就是4/8字节,因此传指针比传值效率更高。

    struct Student *s = (Student*)malloc(sizeof(Student));
    memset(s,0,sizeof(Student));
    printf("%d\n", s->age);
    

    6 字节对齐

    内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址开始访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。

    字节对齐的问题主要就是针对结构体。

    struct MyStruct1
    {
    	short a;  
    	int b;	
    	short c; 
    };
    struct MyStruct2
    {
         short a;
    	short c; 
    	int b;
    };
    //自然对齐
    //1、某个变量存放的起始位置相对于结构的起始位置的偏移量是该变量字节数的整数倍;
    //2、结构所占用的总字节数是结构中字节数最长的变量的字节数的整数倍。
    // short = 2  补 2
    // int = 4
    // short = 2  补 2
    sizeof(MyStruct1) = 12
    // 2个short在一起组成一个 4 
    sizeof(MyStruct2) = 8
    
    #pragma pack(2) //指定以2字节对齐
    struct MyStruct1
    {
    	short a;  
    	int b;	
    	short c; 
    };
    #pragma pack()	//取消对齐
    //short = 2
    //int = 4
    //short = 2
    

    合理的利用字节可以有效地节省存储空间

    不合理的则会浪费空间、降低效率甚至还会引发错误。(对于部分系统从奇地址访问int、short等数据会导致错误)

    二 结构体数组

    结构体声明后,结构体数组与普通数据类型数组的数组一样

    1 第一种方式初始化数组

    //能够识别,结构清晰,可以一眼看出初始化是否有问题
    struct Student stu[3] = { { "lucy", 20 },{ "lilei", 32 },{ "Hanmeimei", 35 } };
    
    //也支持不用{},但不建议:
    //struct Student stu[3] = {"lucy", 20 , "lilei", 32 ,"Hanmeimei", 35 }; 
    
    

    2 第二种方式初始化数组

    struct Student s[5];
    
    for (int i = 0;i < 5;i++) {
    		s[i].age = 20 + i;
    		strcpy(s[i].name, "lucy");
    }
    
    for (int i = 0;i < 5;i++) {
    		printf("s %d:%s,%d\n", i, s[i].name, s[i].age);
    }
    

    三 结构体指针

    1. 赋值
    struct Student stu[3] = { { "lucy", 20 },{ "lilei", 32 },{ "Hanmeimei", 35 } };
    struct Student * stud = stu;
    
    1. 单独定义,分配内存,初始化并使用
    struct Student {
    	char * name;
    	int age;
    };
    
    int test4() {
    
    	struct Student * stud;
    	//分配内存
    	stud = (Student *)malloc(sizeof(struct Student) * 4);
    	//初始化
    	memset(stud, 0, sizeof(struct Student) * 4);
    
    	for (int i = 0;i < 4;i++) {
    	//	(stud + i)->age = 20 + i;
    	//	(stud + i)->name = (char * )"lucy";
    
    		//也可写成如下,因为初始化的时候具备了数组属性
    		stud[i].age = 20 + i;
    		stud[i].name = (char *)"lucy";
    	}
    	for (int i = 0;i < 4;i++) {
    		printf("stud %d: %s, %d\n", i, (stud + i)->name, (stud + i)->age);
    	}
    
    	system("pause");
    	return 0;
    }
    
    

    运行结果:
    stud 0: lucy, 20
    stud 1: lucy, 21
    stud 2: lucy, 22
    stud 3: lucy, 23

    四 结构体中添函数指针成员变量

    struct Man {
    	int age;
    	char *name;
    	int(*Msg)(char *, int);
    };
    
    int message(char * str, int age) {
    	//创建一个窗口
    	MessageBox(0, TEXT("hello"), TEXT("Lijian"), 0);
    	return 0;
    }
    
    int test4() {
    	struct Man man;
    	man.age = 40;
    	man.name = (char *)"lijian";
    	man.Msg = message;
    
    	man.Msg((char *)man.name, man.age);
    
    	system("pause");
    	return 0;
    }
    

    五 结构体中添加结构体指针成员变量

    struct Node {
    	int data;
    	Node * next;
    };
    
    //在单链表的末尾添加一个数据
    int enqueNode(Node *head, int data) {
    	Node * node = (Node *)malloc(sizeof(Node));
    	if (node == NULL) {
    		return 0;
    	}
    	node->data = data;
    	node->next = NULL;
    
    	//用p是为了不改变head的值
    	Node *p = head;
    	while (p->next != NULL) {
    		p = p->next;
    	}
    	p->next = node;
    
    	return 1;
    }
    
    int test4() {
    	Node * list;
    	list = (Node *)malloc(sizeof(struct Node));
    	list->data = 0;
    	list->next = NULL;
    
    	int num = 10;
    	int i = 0;
    	for (i = 0; i < num; i++) {
    		enqueNode(list, i + 1);
    	}
    
    	while (list->next != NULL)
    	{
    		printf("%d \n", list->data);
    		list = list->next;
    	}
    	system("pause");
    	return 0;
    }
    

    输出:
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

    六 Demo

    lsn04

    展开全文
  • 结构体中成员到底如何存储

    千次阅读 2013-09-04 00:03:32
    编译器按照成员顺序一个接一个地给每个成员分配内存,但是由于要考虑到正确的边界对齐要求,成员之间会出现用于填充的额外内存空间(内存对齐)。 为什么有边界对齐? 当内存的值合理对齐时,很多机器能非常高效...

                                                                                         结构的存储分配

    编译器按照成员的顺序一个接一个地给每个成员分配内存,但是由于要考虑到正确的边界对齐要求,成员之间会出现用于填充的额外内存空间(内存对齐)。

    为什么有边界对齐?

    当内存中的值合理对齐时,很多机器能非常高效地访问,而且,有些机器根本就不能访问没有对齐的地址。

    结构的内存对齐主要有一下几个原则:

    1)结构体变量的首地址是其最长基本类型成员的整数倍

    备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能是该基本数据类型的整倍的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为对齐模数。

    2)结构体每个成员相对于结构体首地址的偏移量(offset)都是此成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);

    备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,否则,在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。

    3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)。

    备注:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。

     4)结构体内类型相同的连续元素将在连续的空间内,和数组一样。

     5)如果结构体内存在长度大于处理器位数的元素,那么就以处理器的倍数为对齐单位;否则,如果结构体内的元素的长度都小于处理器的倍数的时候,便以结构体里面最长的数据元素为对齐单位。

     

    1struct {

                     short a1;

                     short a2;

                     short a3;

                     }A;

     

              struct{

                     long a1;

                     short a2;

                     }B;

    sizeof(A) = 6;这个很好理解,三个short都为2

    sizeof(B) = 8;这个是不是比预想的大2个字节?long4short2,整个为8

       2struct A{

                      int a;

                      char b;

                      short c;

                      };

     

             struct B{

                      char b;

                      int a;

                      short c;

                      };

    sizeof(A) = 8; int4char1short2,这里用到了原则1和原则3

    sizeof(B) = 12;是否超出预想范围?char1int4short2,怎么会是12?还是原则1和原则3

    深究一下,为什么是这样,我们可以看看内存里的布局情况。

                     a         b         c

       A的内存布局:1111,     1*,       11

                     b          a        c

       B的内存布局:1***,     1111,   11**

    其中星号*表示填充的字节。A中,b后面为何要补充一个字节?因为cshort,其起始位置要为2的倍数,就是原则1c的后面没有补充,因为bc正好占用4个字节,整个A占用空间为4的倍数,也就是最大成员int类型的倍数,所以不用补充。

    B中,bchar1b后面补充了3个字节,因为aint4,根据原则1,起始位置要为4的倍数,所以b后面要补充3个字节。c后面补充两个字节,根据原则3,整个B占用空间要为4的倍数,c后面不补充,整个B的空间为10,不符,所以要补充2个字节。

    再看一个结构中含有结构成员的例子:

          3struct A{

                         int a;

                         double b;

                         float c;

                        };

                    struct B{

                         char e[2];

                         int f;

                         double g;

                         short h;

                         struct A i;

                        };

    sizeof(A) = 24;这个比较好理解,int4double8float4,总长为8的倍数,补齐,所以整个A24

    sizeof(B) = 48;看看B的内存布局。

    11* *,1111,11111111, 11 * * * * * *, 1111* * * *, 11111111, 1111 * * * *

    i其实就是A的内存布局。i的起始位置要为24的倍数,所以h后面要补齐。

     

    由于内存对齐会造成空间浪费,所以,可以在声明中对结构的成员进行重排让那些对边界要求严格(宽度大)的成员先出现(数组成员应该根据它成员的大小来判断其大小,而不是整个数组的大小),对边界要求最弱的最后出现

    但是有时候这样会导致结构的可读性和可维护性降低,当程序创建几百个甚至几千个结构时,减少内存浪费的要求比程序的可读性更为急迫。这时,可以在声明中添加注释来减少可读性方面的损失。

     

    使用宏确定结构体中的成员的偏移量:

    使用ANSI C<stddef>中定义的offsetof()

    如:

        1/* offsetof example */

        2#include <stdio.h>      /* printf */

        3#include <stddef.h>    /* offsetof */

        4

        5struct foo{

        6    char a;

        7    char b[10];

        8    char c;

        9};

       10

       11intmain(void)

       12{

       13    printf("offsetof(struct foo,a) is %d\n",(int)offsetof(struct foo,a));

       14    printf("offsetof(struct foo,b) is %d\n",(int)offsetof(struct foo,b));

       15    printf("offsetof(struct foo,c) is %d\n",(int)offsetof(struct foo,c));

       16    

       17    return0;

       18}

       19

       20/*

       21 * output:

       22 * offsetof(struct foo,a) is 0

       23 * offsetof(struct foo,b) is 1

       24 * offsetof(struct foo,c) is 11

       25 *

       26 */

    展开全文
  • 一个结构体变量定义完之后,其在内存存储并不等于其所包含元素的宽度之和。 例一: #include <iostream> using namespace std; struct X {

    一个结构体变量定义完之后,其在内存中的存储并不等于其所包含元素的宽度之和。
    例一:

                                      #include <iostream>
    
                                      using namespace std;
    
                                         struct X
    
                                         {
    
                                              char a;
    
                                              int b;
    
                                              double c;
    
                                         }S1;
    
    
    
                                     void main()
    
                                    {
    
                                         cout << sizeof(S1) << endl;
    
                                         cout << sizeof(S1.a) << endl;
    
                                         cout << sizeof(S1.b) << endl;
    
                                         cout << sizeof(S1.c) << endl;
    
                                    }
    
     比如例一中的结构体变量S1定义之后,经测试,会发现sizeof(S1)= 16,其值不等于sizeof(S1.a) = 1、sizeof(S1.b) = 4和 sizeof(S1.c) = 8三者之和,这里面就存在存储对齐问题。
    
    ***原则一:结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存中时,它都会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始(以结构体变量首地址为0计算)。***
    
    比如此例,首先系统会将字符型变量a存入第0个字节(相对地址,指内存开辟的首地址);然后在存放整形变量b时,会以4个字节为单位进行存储,由于第一个四字节模块已有数据,因此它会存入第二个四字节模块,也就是存入到4~8字节;同理,存放双精度实型变量c时,由于其宽度为8,其存放时会以8个字节为单位存储,也就是会找到第一个空的且是8的整数倍的位置开始存储,此例中,此例中,由于头一个8字节模块已被占用,所以将c存入第二个8字节模块。整体存储示意图如图1所示。
    
    
    
    考虑另外一个实例。
    

    例二:

                                           struct X
    
                                           {
    
                                                char a;
    
                                                double b;
    
                                                int c;
    
                                            }S2;
    
    在例二中仅仅是将double型的变量和int型的变量互换了位置。测试程序不变,测试结果却截然不同,sizeof(S2)=24,不同于我们按照原则一计算出的8+8+4=20,这就引出了我们的第二原则。
    
    
    
    
    
    ***原则二:在经过第一原则分析后,检查计算出的存储单元是否为所有元素中最宽的元素的长度的整数倍,是,则结束;若不是,则补齐为它的整数倍。***
    
    例二中,我们分析完后的存储长度为20字节,不是最宽元素长度8的整数倍,因此将它补齐到8的整数倍,也就是24。这样就没问题了。其存储示意图如图2所示。
    
    
    
    掌握了这两个原则,就能够分析所有数据存储对齐问题了。再来看几个例子,应用以上两个原则来判断。
    

    例三:

                                              struct X
    
                                              { 
    
                                                   double a;
    
                                                   char b;
    
                                                   int c;     
    
                                              }S3;
    
    首先根据原则一来分析。按照定义的顺序,先存储double型的a,存储在第0~7个字节;其次是char型的b,存储在第8个字节;接下来是int型的c,顺序检查后发现前面三个四字节模块都被占用,因此存储在第4个四字节模块,也就是第12~15字节。按照第一原则分析得到16个字节,16正好是最宽元素a的宽度8的整数倍,因此结构体变量S3所占存储空间就是16个字节。存储结构如图3所示。
    

    例四:

                                              struct X
    
                                              { 
    
                                                   double a;
    
                                                   char b;
    
                                                   int c;
    
                                                   char d;   
    
                                              }S4;
    
    
    
    仍然首先按照第一原则分析,得到的字节数为8+4+4+1=17;再按照第二原则补齐,则结构体变量S4所占存储空间为24。存储结构如图4所示:
    

    例五:

                                              struct X
    
                                              { 
    
                                                   double a;
    
                                                   char b;
    
                                                   int c;
    
                                                   char d;
    
                                                   int e; 
    
                                               }S5;
    
    同样结合原则一和原则二分析,可知在S4的基础上在结构体内部变量定义最后加入一个int型变量后,结构体所占空间并未增加,仍为24。存储结构示意图如图5所示。
    

    例六:

    如果将例五中加入的变量e放到第一个定义的位置,则情况就不同了。结构体所占存储空间会变为32。其存储结构示意图如图6所示。
    
                                              struct X
    
                                              { 
    
                                                  int e;
    
                                                  double a;
    
                                                  char b;
    
                                                  int c;
    
                                                  char d;
    
                                              }S6;
    
    
    
    补充:前面所介绍的都是元素为基本数据类型的结构体,那么含有指针、数组或是其它结构体变量或联合体变量时该如何呢?
    
    1.包含指针类型的情况。只要记住指针本身所占的存储空间是4个字节就行了,而不必看它是指向什么类型的指针。
    

    例七:

                    struct X              struct Y               struct Z
    
                    {                     {                      {     
    
                       char *a;              int *b;                 double *c;
    
                    };                     };                     };
    
    经测试,可知sizeof(X)、sizeof(Y)和sizeof(Z)的值都为4。
    
    2.含有构造数据类型(数组、结构体和联合体)的情况。首先要明确的是计算存储空间时要把构造体看作一个整体来为其开辟存储空间;其次要明确的是在最后补齐时是按照所有元素中的基本数据类型元素的最长宽度来补齐的,也就是说虽然要把构造体看作整体,但在补齐的时候并不会按照所含结构体所占存储空间的长度来补齐的(即使它可能是最长的)。
    

    例八:

                                      struct X
    
                                     {
    
                                          char a;
    
                                          int b;
    
                                          double c;
    
                                      };
    
                                      struct Y
    
                                      {
    
                                           char a;
    
                                           X b;
    
                                       };
    
    经测试,可知sizeof(X)为16,sizeof(Y)为24。即计算Y的存储长度时,在存放第二个元素b时的初始位置是在double型的长度8的整数倍处,而非16的整数倍处,即系统为b所分配的存储空间是第8~23个字节。
    
    如果将Y的两个元素char型的a和X型的b调换定义顺序,则系统为b分配的存储位置是第0~15个字节,为a分配的是第16个字节,加起来一共17个字节,不是最长基本类型double所占宽度8的整数倍,因此要补齐到8的整数倍,即24。测试后可得sizeof(Y)的值为24。
    
    由于结构体所占空间与其内部元素的类型有关,而且与不同类型元素的排列有关,因此在定义结构体时,在元素类型及数量确定之后,我们还应该注意一下其内部元素的定义顺序。
    
    展开全文
  • 来源:网络,排版整理:晓宇微信公众号:芯片之家(ID:chiphome-dy)结构体的定义结构体(struct)是由系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。结构体和其他类型基础数据类型一样,例如int类型,...
  • C语言中结构体对齐原则   原则1、数据成员对齐规则:结构(struct或联合union)的数据... 原则2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储
  • 结构体

    2019-11-10 16:19:33
    一个基本数据类型无法解决的问题,由结构体来完成。 数组也可以存放多个数据,但是要求数据类型一致,所以无法使用。 结构体声明 struct 结构体声明 { 结构体成员1; 结构体成员2; 结构体成员3; ... }; struct ...
  • 结构体成员内存对齐规则

    千次阅读 2018-03-01 16:13:47
    原则1:结构体中元素是按照定义顺序一个一个放到内存去的,但并不是 紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存时,它都 会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在...
  • 设计一个函数,能够对输入的两个学生结构体信息的成绩按照大小顺序输出。要求使用指针类型的变量进行结构体变量的定义。 解题思路:采用 malloc 函数进行结构体指针变量的定义,并使用 --> 访问成员变量的方式...
  •  有人问WNDCLASSEX结构体中cbWndExtra成员到底是做什么用的,在网上也查了一些资料,但说的都不太正确,MSDN上说的也较为含糊,但这cbWndExtra成员的作用确实是较为重要,首先Windows默认的对话框类会用到它(即...
  • 结构体在内存是如何存储

    千次阅读 2014-05-14 12:34:38
    一个结构体变量定义完之后,其在内存存储并不等于其所包含元素的宽度之和。 例一:  #include  using namespace std;  
  • //文件存放了20个由小到大的排列的整数,现在从键盘上输入一个数,要求把该数插入此文件,保持文件特性不变。 //基本思想是:先从文件读取那20个数放入字符数组,然后再对字符数组进行操作 #include<...
  • 函数指针:指向函数的指针,如果在程序定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义...
  • c语言结构体学习整理(结构体初始化,结构体指针)

    万次阅读 多人点赞 2018-11-01 20:22:12
    c语言交换两个结构体的值(结构体指针) 1关于语言的结构体: 首先我们为什么要用到结构体,我们都已经学了很多int char …等类型还学到了同类型元素构成的数组,以及取上述类型的指针,在一些小应用可以灵活...
  • 大中小C语言中结构体详解2018-01-20大家都知道学习嵌入式培训讲师东哥为大家带来关于:C语言中结构体详解,希望能帮助到更多的嵌入式学习者。...声明一个结构休类型的一般形式如下:struct 结构体名{成员列表};...
  • 结构体中结构体指针是使用、问题背景二、代码、说明 、问题背景   日常工作没有编程的机会,所以只看得懂代码,现在需要重新写段代码,实现固定格式存储数据,需要使用到结构体结构体指针。数据...
  • 结构体元素顺序结构体的大小

    千次阅读 2004-08-22 17:28:00
    说明:暑假看书想到的一点东西,因当时没有电脑,... 先看一个例子,有三个结构体的定义如下:struct a { bool b1; bool b2; int i1; int i2; int i3;};struct b{ int i1; int i2; int i3; bool
  • 前面已经说过,位域成员不能单独被取sizeof值,我们这里要讨论的是含有位域的结构体的sizeof,只是考虑到其特殊性而将其专门列了出来。 C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了...
  • 结构体在内存存储方式

    千次阅读 多人点赞 2018-07-03 21:22:00
    一个结构体变量定义完之后,其在内存存储并不等于其所包含元素的宽度之和。例一:#include &lt;iostream&gt; using namespace std; struct X { char a; int b; double c; }S1; int main() { ...
  • 最近在看鸡啄米关于c++的教程,偶然发现了结构体中两个好玩的东西。...以一个结构体为例:  struct si{  char x[5];  char y;  float z;  double m;  }su; 我用的su.x="abcd"和直接在定义是初始化,均报错
  • 结构体大小

    千次阅读 2018-07-09 22:47:11
    结构体中成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。然后我们看...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 50,733
精华内容 20,293
关键字:

一个结构体中三个成员的存储顺序