2025年位段×友元

位段×友元目录 位段 友元 位段 位段结构的一般类型是 struct 位段名 成员列表 举一个小例子 struct word unsigned coulor 4 也可以用 unsigned

大家好,我是讯享网,很高兴认识大家。

目录

位段:

友元:


位段:

位段结构的一般类型是:

struct 位段名

{

成员列表

};

举一个小例子:

struct word

{

unsigned coulor:4;//也可以用unsigned int 替代unsigned,两种方法是等效的

unsigned size:1;

unsigned kinds:2;

};

        这里coulor代表字的颜色,size为字号,kinds为字的语言种类,大家看一下它的结构,是不是与结构体有几分神似?

如果用结构体来声明这个位段,它是怎么样的呢?

struct word

{

unsigned coulor;

unsigned size;

unsigned kinds;

};

咋一看,位段和结构体的差别是位段的成员后面都跟着一个数字,结构体的成员后面就没有出现

在C语言中,位段的声明和结构(struct)类似,但它的成员是一个或多个位的字段,这些不同长度的字段实际储存在一个或多个整型变量中。在声明时,位段成员必须是整形或枚举类型(通常是无符号类型),且在成员名的后面是一个冒号和一个整数整数规定了成员所占用的位数。位域不能是静态类型。不能使用&对位域做取地址运算,因此不存在对位域的指针。                                                                                                                 ------------>百度

        为什么会出现位段这种结构呢?先想想。事实上,计算机内部要用至少一个字节来存储相应的信息。例如,最小的char类型用的就是一个字节。现在我们想一个情景上的问题:

你现在手里头有10种颜色,1~10一个数字代表一种,你要怎样操作使机器按照你的想法依次为物体涂上不同的颜色?

 1~10对应的二进制数如下:

1   2   3   4   5   6   7   8   9   10
1 10 11 100 101 110 111 1000 1001 1010

        我们看到,用二进制数来代表1~10,最多用到了4个二进制位,这也就是说,用四个位就能表示1~10间的任意一个数。然而,存储一次信息至少要用到1个字节,即8个二进制位。那么,有没有一种数据类型可以让我只是控制存储信息所用的位数呢?于是,位段这种构造类型应运而生。我们讲回最初的位段的例子,在内存中,它的结构示意是这样的:

 
讯享网

        图中的数字均为二进制位的位数,可以看出,总共用了7位,还有一位是空闲的(计算机以一个字节作为读取信息的单位)。如果我们又有一些新信息要进行存储,比如一个字的粗细,它有两种可能——粗或细,可以用0或1来表示,用到了一个二进制位,刚好可以占用这个空闲位。如果你要将它放入下一个字节,该怎么做呢?

只需要加一个unsigned:0;即:

struct word

{

unsigned coulor:4;//上一个字节到此为始

unsigned size:1;

unsigned kinds:2;//上一个字节到此为止

unsigned:0;

unsigned thick:1;//下一个字节到此为始

};

当然,位段中定义的第一个字段的长度不能为0,这是不合理的,因为你空了一整个字节

        说到这里,各位博友应能体会到:一个字段必须存储在同一个存储单元(一般为1个字节,这只是一般情况啊),不能横跨两个存储单元。如果本单元的剩余空间不能够容纳某一位段了,那么就从下一存储单元开始继续存储

说到位段的应用,举个例子:

//Signle-precision format. union ieee754_float { float f; struct { unsigned int matissa : 23; unsigned int exponent : 8; unsigned int negative : 1; }ieee; };

讯享网

这个例子来源于<ieee754.h>,共用体中套用了一个位段,这个位段中,我们可以看到float类型的位的分配。首先,float类型的数据由4个字节,32个位组成,示意图:

符号位:1 指数位:8 尾数位:23

                                                单精度(32位)

这里单精度数据的存储单元就是4个字节。

1.可以用"%d"、"%x"、"%u"、"%o"等格式字符,以整数形式输出位段。

2.在数值表达式中引用位段时,系统自动地将位段转换为整型数。

                                                                                        ————源自查找的资料(无链接)

        其实,位段就是另一种结构体,它的定义变量的方式与结构体的定义变量的方式没有差别,就不再另行阐述,若掌握不牢固,建议回看这篇博文:结构体×共用体×枚举类型。

接下来就是实践了,按照最初的那个位段:

struct word

{

unsigned coulor:4;

unsigned size:1;

unsigned kinds:2;

};

/*

coulor:

1 2 3 4 5 6 7 8 9 10
绿 墨绿 深红

size:

0 1
大号 小号

kinds:

0 1 2 3
中文 English Русский ﹝にほんご﹞

注:对应的数字代表不同的选项

*//

上一串代码:

讯享网#include<stdio.h> struct word { unsigned coulor : 4; unsigned size : 1; unsigned kinds : 2; }; void Menu_coulor() { printf("--------------------------------------\n"); printf("\t\tMENU\t\n"); printf("\t1.红\t2.橙\t3.黄\n"); printf("\t4.绿\t5.青\t6.蓝\n"); printf("--------------------------------------\n"); printf("Input your option please:"); } int main() { struct word word1; int coulor; Menu_coulor(); scanf_s("%d",&coulor); word1.coulor = coulor; switch (word1.coulor) { case 1: printf("字体的颜色为红色"); break; case 2: printf("字体的颜色为橙色"); break; case 3: printf("字体的颜色为黄色"); break; case 4: printf("字体的颜色为绿色"); break; case 5: printf("字体的颜色为青色"); break; default: printf("字体的颜色为蓝色"); break; } return 0; }

注:鉴于打出完整的代码太费时间,故只打出部分代码 

在数值表达式中引用位段时,系统自动地将位段转换为整形数。

        由这条规则,我们可以用位段来存储我们的信息。通过上面的代码,我们可以看到,位段变量的使用和结构体变量的使用无明显差别

但是,凡事总有例外:

不能使用&对位域做取地址运算,因此不存在位域的指针,编译器通常不支持位域的引用(reference)。                                                        ————文章上面引用的资料有提到

在上面的代码中:

    struct word word1;
    int coulor;
    Menu_coulor();
    scanf_s("%d",&coulor);
    word1.coulor = coulor;

若将这段代码简化为:

struct word word1;

Menu_coulor();

 scanf_s("%d",word.coulor);

按理来说,简化后的代码更符合我们一般的书写逻辑不是吗?但就像上面提到的:不能使用&对位域做取地址运算。否则你的编译器会报出这样的错误原因:

 而通过引进中间变量coulor,我们就解决了这个问题。

好了,位段的讲解到此为止。


友元:

        友元是C++语言中的一种构造类型,要认识这个类型,我想我们需要先理解类结构体这个知识点。类结构体是什么呢?既然它有“结构体”这个词眼,那么它当然和我们先前讲过的结构体是脱不了干系的。我们看一下类结构体的基本结构:

class 类体名

{

public:

        数据成员;

        成员函数;

private:

        数据成员;

        成员函数;

protected:

        数据成员;

        成员函数;

};

        不难看出,声明一个类结构体用的是class关键字,而其内部被public、private、protected关键字划分为了3个部分,与结构体有着很相似的地方。在public关键字的作用域中,内部的数据成员与普通结构体中的数据成员使用无异,不过public区域中的成员函数以及其它两个关键字的作用域中数据成员以及成员函数的使用又有何特殊之处呢?

对于private、protected关键字下文不解释,博主能力有限,希望链接详情的博友可以看这位前辈写的这篇博客:private关键字

先从成员函数讲起,类结构体比结构体多了一个主要功能,那就是对内部数据的操作行为,这个行为即在类体内部的成员函数。

#include<stdio.h> class cStudent { public://必须加上public,否则无法直接执行内部操作 int iNum; char sName[20]; int putname(char sNmae[20]) { printf("%s",sName); return 0; } int getname() { gets(sName); return 0; } }; int main() { cStudent stu; stu.getname(); printf("%s",stu.putname(stu.sName)); return 0; } 

        在这个例子中,我们在main()函数中声明了一个对象即stu,可以看到,通过在cStudeng这个类体定义的内部函数getname()、putname(),我们可以实现对同一个对象的数据成员进行操作:更改它的值或是将它打印出来,而我们只需要像结构体中引用变量的方式那样:

1.struct 结构体名 变量名;

变量名.结构体成员变量可以作为被引用的表达式

2.struct 结构体名* 指针变量名;

指针变量名->结构体成员变量可以作为被引用的表达式

通过同样的方式,我们在类体中不仅可以引用已经被定义的对象的数据成员,也可以引用它的成员函数

千万注意:成员函数中的形式参量必须是在类体中已经定义好的数据成员。

        如果在类体的声明中不用public关键字,那会默认使用private关键字(注意不是protected关键字)protected和private 在当前class范围外不可访问,除非友元

友元,在于一个“友”,对应的关键字也是“friend”。

        友元怎么用呢?下面是个完整的实例,不太了解的博友其实可以上机试试,看看改个参数什么的会发生什么变化。对了,由于本人经常用的编译器VS2017并没有下载C++编译环境的插件,故上面以及接下来的代码都是在Dev-C++上码出来的代码。

讯享网#include<stdio.h> class cStudent { int putname(char sNmae[20]) { printf("%s",sName); } //默认为私有成员,即在private辖域内 public: friend class sStudent; //这里cStudent类将sStudent类作为自己的友元类 int iNum; char sName[20]; int getname() { gets(sName); return 0; } }; class sStudent { cStudent stu; //因为cStudent类将sStudent类作为自己的友元类, //所以这里可以用cStudent类来定义一个stu对象 public: void get_put_infom() { stu.getname(); //这里我们调用了cStudent类的公有方法 stu.putname(stu.sName); //这里我们调用了cStudent类的私有方法 } } ; int main() { sStudent stud; //这里我们用sStudent类定义了一个stud对象 stud.get_put_infom(); //这里我们调用了sStudent类的公有方法 return 0; } 

代码片中注释有点模糊,这里再解释一遍:

首先,你如果要在sStudent类中调用cStudent类中的私有方法(私有方法即在private辖域内的函数和变量),注意是私有方法而非公有方法,你需要在声明sStudent类前添加上语句:friend class sStudent;,你将这条语句添加在公有域也好,私有域也罢,加上就行了。这之后你才能在sStudent类中调用cStudent类中的私有方法,同时,你别忘了在声明sStudent类的过程声明一个cStudent类的对象stu,不然你是不能直接利用cStudent类中的私有方法的。

接下来我们要在main()函数中用sStudent类再声明一个对象stud,通过这个对象我们就能调用sStudent类中的公有方法啦。

对于类和友元的初步解释就此为止了。


写在后面:

这篇博文拖了有足足一个星期了,实在是顾不太上,因为最近要复习高数、普通物理、离散数学、四级英语,望多多涵量。


欢迎指正我的上一篇博客:一题多解×3

我的下一篇博客:一题多解×4

小讯
上一篇 2025-01-09 18:27
下一篇 2025-04-08 18:16

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/69966.html