第10课struct和union分析(代码片段)

wanmeishenghuo wanmeishenghuo     2022-12-25     552

关键词:

struct的小秘密:空结构体占多大内存呢?

技术分享图片

 

直观的答案有两种:

  1、空结构体的大小为0

  2、结构体本来就是为了将不同的变量集合在一起使用的,定义空结构体会导致编译错误

实例分析:

 1 #include <stdio.h>
 2 
 3 struct TS
 4 
 5 
 6 ;
 7 
 8 int main()
 9 
10     struct TS t1;
11     struct TS t2;
12     
13     printf("sizeof(struct TS) = %d
", sizeof(struct TS));
14     printf("sizeof(t1) = %d, &t1 = %p
", sizeof(t1), &t1);
15     printf("sizeof(t2) = %d, &t2 = %p
", sizeof(t2), &t2);
16     
17     return 0;
18 

gcc编译运行如下所示:

技术分享图片

 

用bcc编译器对上述程序进行编译,结果如下:

技术分享图片

 

bcc不允许定义空结构体。

用vc编译器编译结果如下:

技术分享图片

 

vc编译器也不允许定义空结构体。

结构体与柔性数组:

技术分享图片

 

在C语言中,结构体的最后一个元素可以定义成int array[]的形式。大小待定的数组即为柔性数组。

示例:

技术分享图片

 

柔性数组的用法:

技术分享图片

 

SoftArray的成员只有len。array[]只是一个标识,实际使用时代表的是len之后的动态申请的空间。

示例:

 1 #include <stdio.h>
 2 #include <malloc.h>
 3 
 4 struct SoftArray
 5 
 6     int len;
 7     int array[];
 8 ;
 9 
10 struct SoftArray* create_soft_array(int size)
11 
12     struct SoftArray* ret = NULL;
13     
14     if( size > 0 )
15     
16         ret = (struct SoftArray*)malloc(sizeof(struct SoftArray) + sizeof(int) * size);
17         
18         ret->len = size;
19     
20     
21     return ret;
22 
23 
24 void delete_soft_array(struct SoftArray* sa)
25 
26     free(sa);
27 
28 
29 void func(struct SoftArray* sa)
30 
31     int i = 0;
32     
33     if( NULL != sa )
34     
35         for(i=0; i<sa->len; i++)
36         
37             sa->array[i] = i + 1;
38         
39      
40 
41 
42 int main()
43 
44     int i = 0;
45     struct SoftArray* sa = create_soft_array(10);
46     
47     func(sa);
48     
49     for(i=0; i<sa->len; i++)
50     
51         printf("%d
", sa->array[i]);
52     
53     
54     delete_soft_array(sa);
55     
56     return 0;
57 

运行结果如下:

技术分享图片

 

  柔性数组的好处在于,我们的func函数只需要一个指向柔性数组的指针就好了,而不需要数组大小的参数。也不用在定义数组的时候就预先指定数组的大小。这样既方便又好用。

C语言中的union:

技术分享图片

 

 

union的注意事项:

技术分享图片

 

判断系统的大小端:

 1 #include <stdio.h>
 2 
 3 int system_mode()
 4 
 5     union SM
 6     
 7         int i;
 8         char c;
 9     ;
10 
11     union SM sm;
12     
13     sm.i = 1;
14     
15     return sm.c;
16 
17 
18 
19 int main()
20 
21     printf("System Mode: %d
", system_mode());
22     return 0;
23 

运行结果如下:

技术分享图片

 

可见当前运行在小端模式系统。

在使用联合体时一定要注意大小端。

小结:

  struct中的每个数据成员有独立的存储空间

  struct可以通过最后的数组标识符产生柔性数组,柔性数组的好处在于可以在程序运行阶段得到一个数组,并且带长度信息

  union中的所有成员共享同一个存储空间

  union的使用会受到系统大小端的影响

 

第23课#error和#line使用分析(代码片段)

#error的用法: 示例程序:1#include<stdio.h>23#ifndef__cplusplus4#errorThisfileshouldbeprocessedwithC++compiler.5#endif67classCppClass89private:10intm_value;11public:12CppClass()1314151617~CppClas 查看详情

第17课++和--操作符分析(代码片段)

++和--操作符对应两条汇编指令: 上图中的表达式,我们的初步分析如下: 完整的示例程序如下:1#include<stdio.h>23intmain()45inti=0;6intr=0;78r=(i++)+(i++)+(i++);910printf("i=%d",i);11printf("r=%d",r);1213r=(++i)+(++i)+(++i);1 查看详情

oracle开发者中级第4课(分析函数)实验(代码片段)

概述本实验参考DevGym中的实验指南。创建环境首先创建表:createtablebricks(brick_idinteger,colourvarchar2(10),shapevarchar2(10),weightinteger);insertintobricksvalues(1,'blue','cube',1);insertintobricksval 查看详情

第22课条件编译使用分析(代码片段)

条件编译的基本概念: 条件编译就是利用预处理器的功能来对代码进行一些删除操作。程序示例:1#include<stdio.h>23#defineC145intmain()67constchar*s;89#if(C==1)10s="Thisisfirstprintf...";11#else12s="Thisissecondprintf...";13#endif1415p 查看详情

第32课数组指针和指针数组分析(代码片段)

问题思考: 在二维数组的时候就不能用数组名表达数组首元素了。matrix不再代表数组首元素的地址。数组类型: intarray[5]的类型为int[5],而不是int型。int[5]说明这个数组有5个元素,每个元素类型是int。定义数组类型:&nb... 查看详情

struct和union区别(代码片段)

题目1:有如下结构体structAlonga1;shorta2;inta3;int*a4;;请问在64位编译器下用sizeof(structA)计算出的大小是多少? 内存对齐成员对齐有一个重要的条件,即每个成员按自己的方式对齐。其对齐的规则是:每个成员按其类... 查看详情

第9课const和volatile分析(代码片段)

const只读变量: const全局变量的分歧: 测试程序与运行结果如下: 通过指针修改const全局变量的例子: 结果如下: 可见修改const的全局变量会导致程序崩溃。原因是const全局变量被存储于只读存储区了。上图... 查看详情

第8课goto和void分析(代码片段)

遭人遗弃的goto: C语言是一种面向过程的结构化语言,其中主要结构有三种,顺序执行、选择执行、循环执行。再复杂的程序也是由这三种结构组合而成的。goto破坏了结构化特性,使程序以第四种方式执行,结构化特性被破... 查看详情

第5课引用的本质分析(代码片段)

引用作为变量别名而存在,因此在一些场合可以代替指针引用相对于指针来说具有更好的可读性和实用性swap函数的实现对比如下: 注意:  函数中的引用形参不需要进行初始化。示例程序如下: 形参没有初始化,而... 查看详情

第47课递归函数分析(代码片段)

递归的数学思想: 递归函数: 递归函数设计技巧: 递归函数设计示例一: 递归版strlen:1#include<stdio.h>23intstrlen_r(constchar*s)45if(*s)67return1+strlen_r(s+1);89else1011return0;12131415intmain()1617printf 查看详情

第8课函数重载分析(上)(代码片段)

重载(Overload): C++中的函数重载: 函数重载示例:1#include<stdio.h>2#include<string.h>34intfunc(intx)56returnx;789intfunc(inta,intb)1011returna+b;121314intfunc(constchar*s)1516returnstrlen(s 查看详情

第55课:在线广告点击流处理代码的分析和实现

重点内容 查看详情

第24课#pragma使用分析(代码片段)

#pragma是C语言留给编译器厂商进行扩展用的。这个关键字在不同的编译器之间也许是不能够移植的。#pragma简介 #pragmamessage #pragmamessage打印的消息并不代表代码有什么问题。示例:1#include<stdio.h>23#ifdefined(ANDROID20)4#pragmam... 查看详情

联合体(共用体)(代码片段)

...memberdefinition;...memberdefinition;[oneormoreunionvariables];只不过将struct换成了union在使用的时候也是用.符号获取成员信息。  本文主要讲一下结构体和联合体的不同看下面的例子:#include<stdio.h>//结构体structs1charc[11];inti;chara;str... 查看详情

第10课分组数据(代码片段)

第10课分组数据10.1数据分组使用分组可以将数据分为多个逻辑组,对每个组进行聚集计算。10.2创建分组分组是使用SELECT语句的GROUPBY子句建立的。SELECTvend_id,COUNT(*)ASnum_prodsFROMProductsGROUPBYvend_id;这就会对每个vend_id而不是整个表计算... 查看详情

第41课内存操作经典问题分析1(代码片段)

野指针: 野指针的由来: 示例程序:1#include<stdio.h>2#include<malloc.h>345intmain()67int*p1=(int*)malloc(40);8int*p2=(int*)1234567;9inti=0;1011for(i=0;i<40;i++)1213*(p1+i)=40-i;141516free( 查看详情

第29课指针和数组分析(下)(代码片段)

数组名可以当做常量指针使用,那么指针是否也可以当做数组名来使用呢? 下标VS指针形式: 示例程序:1#include<stdio.h>23intmain()45inta[5]=0;6int*p=a;7inti=0;89for(i=0;i<5;i++)1011p[i]=i+1;121314for(i=0;i<5;i++)1516printf(" 查看详情

oracle开发者中级第6课(并集差集和交集)实验(代码片段)

概述本实验参考DevGym中的实验指南。创建环境创建2张表:createtablemy_brick_collection(colourvarchar2(10),shapevarchar2(10),weightinteger);createtableyour_brick_collection(heightinteger,widthinteger,depthinteger,colourv 查看详情