宋宝华 21cnbao sweek@21cn.com
试题一:编写一段程序判断系统中的CPU是Little endian还是Big endian模式?
分析:
作为一个计算机相关专业的人,我们应该在计算机组成中都学习过什么叫Little endian和Big endian。Little endian和Big endian是CPU存放数据的两种不同顺序。对于整型、长整型等数据类型,Big endian认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节);而Little endian则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放数据的低位字节到高位字节)。
例如,假设从内存地址0x0000开始有以下数据:
0x0000
0x0001
0x0002
0x0003
0x12
0x34
0xab
0xcd
如果我们去读取一个地址为0x0000的四个字节变量,若字节序为big-endian,则读出结果为0x1234abcd;若字节序位little-endian,则读出结果为0xcdab3412。如果我们将0x1234abcd写入到以0x0000开始的内存中,则Little endian和Big endian模式的存放结果如下:
地址
0x0000
0x0001
0x0002
0x0003
big-endian
0x12
0x34
0xab
0xcd
little-endian
0xcd
0xab
0x34
0x12
一般来说,x86系列CPU都是little-endian的字节序,PowerPC通常是Big endian,还有的CPU能通过跳线来设置CPU工作于Little endian还是Big endian模式。
解答:
显然,解答这个问题的方法只能是将一个字节(CHAR/BYTE类型)的数据和一个整型数据存放于同样的内存开始地址,通过读取整型数据,分析CHAR/BYTE数据在整型数据的高位还是低位来判断CPU工作于Little endian还是Big endian模式。得出如下的答案:
typedef unsigned char BYTE;
int main(int argc, char* argv[])
{
       unsigned int num,*p;
    p = #
       num = 0;
 
    *(BYTE *)p = 0xff;
      
       if(num == 0xff)
       {
              printf("The endian of cpu is little\n");
       }
       else    //num == 0xff000000
       {
              printf("The endian of cpu is big\n");
       }
       return 0;
}
除了上述方法(通过指针类型强制转换并对整型数据首字节赋值,判断该赋值赋给了高位还是低位)外,还有没有更好的办法呢?我们知道,union的成员本身就被存放在相同的内存空间(共享内存,正是union发挥作用、做贡献的去处),因此,我们可以将一个CHAR/BYTE数据和一个整型数据同时作为一个union的成员,得出如下答案:
int checkCPU()
{
 {
  union w
  {
   int a;
   char b;
  } c;
  c.a = 1;
  return (c.b == 1);
 }
}
实现同样的功能,我们来看看Linux操作系统中相关的源代码是怎么做的:
static union { char c[4]; unsigned long l; } endian_test = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l)
Linux的内核作者们仅仅用一个union变量和一个简单的宏定义就实现了一大段代码同样的功能!由以上一段代码我们可以深刻领会到Linux源代码的精妙之处!
试题二:假设网络节点A和网络节点B中的通信协议涉及四类报文,报文格式为“报文类型字段+报文内容的结构体”,四个报文内容的结构体类型分别为STRUCTTYPE1~ STRUCTTYPE4,请编写程序以最简单的方式组织一个统一的报文数据结构。
分析:
报文的格式为“报文类型+报文内容的结构体”,在真实的通信中,每次只能发四类报文中的一种,我们可以将四类报文的结构体组织为一个union(共享一段内存,但每次有效的只是一种),然后和报文类型字段统一组织成一个报文数据结构。
解答:
根据上述分析,我们很自然地得出如下答案:
typedef unsigned char BYTE;
 
//报文内容联合体
typedef union tagPacketContent
{
       STRUCTTYPE1 pkt1;
       STRUCTTYPE2 pkt2;
       STRUCTTYPE3 pkt1;
       STRUCTTYPE4 pkt2;
}PacketContent;
 
//统一的报文数据结构
typedef struct tagPacket
{
       BYTE pktType;
    PacketContent pktContent;
}Packet;
总结
在C/C++程序的编写中,当多个基本数据类型或复合数据结构要占用同一片内存时,我们要使用联合体(试题一是这样的例证);当多种类型,多个对象,多个事物只取其一时(我们姑且通俗地称其为“n选1”),我们也可以使用联合体来发挥其长处(试题二是这样的例证)。

本文出自 “宋宝华的博客” 博客,请务必保留此出处http://21cnbao.blog.51cto.com/109393/120108

[转]从两道经典试题谈C/C++中联合体(union)的使用的更多相关文章

  1. 两道面试题,带你解析Java类加载机制

    文章首发于[博客园-陈树义],点击跳转到原文<两道面试题,带你解析Java类加载机制> 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Gr ...

  2. 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)

    本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...

  3. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  4. js 从两道面试题加深理解闭包与箭头函数中的this

     壹 ❀ 引 在本文之前我已经花了两个篇幅专门介绍了JavaScript中的闭包与this,正好今早地铁上看到了两道面试题,试着做了下发现挺有意思,所以想单独写一篇文章来记录解析过程.若你对于闭包与t ...

  5. Java中创建String的两道面试题及详解

    我们知道创建一个String类型的变量一般有以下两种方法: String str1 = "abcd"; String str2 = new String("abcd&qu ...

  6. 两道JVM面试题,竟让我回忆起了中学时代!

    作者:肥朝 原文链接:https://mp.weixin.qq.com/s/4wJ6ANal0blLOseasfIuVw 中学授课模式 考虑到可能有部分粉丝对JVM参数不清楚,所以我们参照中学的授课模 ...

  7. ASP.NET 经典60道面试题

    转:http://bbs.chinaunix.net/thread-4065577-1-1.html ASP.NET 经典60道面试题 1. 简述 private. protected. public ...

  8. 经典71道Android试题及答案

    本文为开发者奉献了70道经典Android面试题加答案--重要知识点几乎都涉及到了,你还等啥,赶紧收藏吧!! 1. 下列哪些语句关于内存回收的说明是正确的? (b) A. 程序员必须创建一个线程来释放 ...

  9. [ZZ]知名互联网公司Python的16道经典面试题及答案

    知名互联网公司Python的16道经典面试题及答案 https://mp.weixin.qq.com/s/To0kYQk6ivYL1Lr8aGlEUw 知名互联网公司Python的16道经典面试题及答 ...

随机推荐

  1. python输出重定向

    0表示标准输入1表示标准输出2表示标准错误输出> 默认为标准输出重定向,与 1> 相同2>&1 意思是把 标准错误输出 重定向到 标准输出.&>file 意思是 ...

  2. JS闭包研究、自造困扰与解答

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  3. Microsoft visual studio中文字样输出

    解决办法: 可以尝试下通过: 1.file->高级保存选项-> 2.工具->选项->文本编辑器->自动检测不带签名的UTF-8编码

  4. [Flex] ButtonBar系列——垂直布局

    <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="ht ...

  5. AngularJs在单击提交后显示验证信息.

    <!DOCTYPE html> <html ng-app="app"> <head> <meta charset="utf-8& ...

  6. AngularJs创建服务

    在开发中我们总是需要向服务器请求同样的数据,那么我们如何来把他们提取出来进行封装一下呢,这就需要用到服务了. 需要用到关键字factory了. <!DOCTYPE html> <ht ...

  7. ubuntu 14.10 安装 zabbix

    在ubuntu 14.10 上部署 zabbix 2.x 基本软件包安装 既然是ubuntu系统,当然要用好apt-get神器. 参考教程 URL:http://blog.csdn.net/cloud ...

  8. IOS中类似的。9.png图片

    图形用户界面中的图形有两种实现方式,一种是用代码画出来,比如Quartz 2D技术,狠一点有OpenGL ES,另一种则是使用图片. 代码画的方式比较耗费程序员脑力,CPU或GPU; 图片则耗费磁盘空 ...

  9. SQL执行的原理以及一些常见的关键字

    sql语句在面试里面问道的问题: sql的解析的顺序 1.where里面的条件是从右向左扫描解析 2.from里面的大表在前,小表在后,解析的顺序是从右向左解析. 3.left/right/inner ...

  10. Redis多机功能总结

    1.通过Redis的复制功能,用户可以创建指定服务器的任意多个复制品,每个复制品服务器和被复制的原服务器拥有相同的数据: 2.通过将读请求分散给多个从服务器处理,用户可以减少主服务器在处理读请求方面的 ...