我早先使用过工会; 今天,当我读到这篇文章并开始知道这段代码时,我感到震惊
union ARGB
{
uint32_t colour;
struct componentsTag
{
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} components;
} pixel;
pixel.colour = 0xff040201; // ARGB::colour is the active member from now on
// somewhere down the line, without any edit to pixel
if(pixel.components.a) // accessing the non-active member ARGB::components
Run Code Online (Sandbox Code Playgroud)
实际上是未定义的行为即从工会成员读取而不是最近编写的那个导致未定义的行为.如果这不是工会的预期用途,那是什么?有人可以详细解释一下吗?
更新:
事后我想澄清一些事情.
如果标准布局联合包含多个共享公共初始序列的标准布局结构,并且如果此标准布局联合类型的对象包含其中一个标准布局结构,则允许检查任何标准布局结构的公共初始序列.标准布局结构成员.§9.2/ 19:如果相应的成员具有布局兼容类型且两个成员都不是位字段,或者两者都是具有相同宽度的位字段,则一个或多个初始序列的两个标准布局结构共享一个公共初始序列成员.
C89/90在未指明的行为(附件J)中称之为,而K&R的书称其实施已定义.来自K&R的报价:
这是联合的目的 - 一个可以合法地保存几种类型中的任何一种的变量.[...]只要用法一致:检索到的类型必须是最近存储的类型.程序员有责任跟踪当前存储在联合中的类型; 如果将某些内容存储为一种类型并将其提取为另一种类型,则结果将依赖于实现. …
我正在为我的应用程序设计一种文件格式,我显然希望它可以在big-endian和little-endian系统上运行.我已经找到了使用htonl和管理整数类型的工作解决方案ntohl,但是当我尝试使用float和double值时,我有点卡住了.
鉴于浮点表示如何工作的性质,我认为标准的字节顺序函数不适用于这些值.同样,我甚至不完全确定传统意义上的字节顺序是否支配这些类型的字节顺序.
我需要的只是一致性.写double出来的一种方法,并确保我在读回来时获得相同的值.如何在C中执行此操作?
我是C的新手,从书本上学习/在互联网上学习.我正在尝试编写一个我可以传递给任何函数的函数,double并返回一个int在printf("%.*lf" ...语句中使用的函数,这样返回的函数int既不会降低精度也不会产生尾随零.
我有一个工作函数,但它很大,因为它是为了可读性而编写的,所有注释都是如此.
为了总结这个函数,我计算得到该double范围所需的除以10的除法10 > d >= 0,只取小数部分并将其放入string带有n个小数位的位置n = 15 - number_of_digits_left_of_decimal(我读取该类型double只能跟踪15位数),检查string从右到左的尾随零并保持计数,最后返回一个int代表小数点右边非零数字的数字.
有没有更简单的方法?谢谢.
int get_number_of_digits_after_decimal(double d)
{
int i = 0; /* sometimes you need an int */
int pl = 0; /* precision left = 15 - sigfigs */
int sigfigs = 1; /* the number of digits in d */
char line[20]; /* used to find …Run Code Online (Sandbox Code Playgroud) x对于二进制浮点数系统中的数字,最后一位的单位定义为ulp(x) = 2^{E(x)} * 2^{1 - p} = 2^{E(x)}*epsilon,其中指数是用于表示的以 2 为底的指数x,p是数字格式的精度(53对于双精度格式),并且epsilon = 2^{1-p}是机器公差。
看着std::numeric_limits我期望找到类似的东西std::numeric_limits<double>::ulp(x),但这似乎不可用。或者类似的东西std::numeric_limits<double>::exponent(x)我可以乘以std::numeric_limits<double>::epsilon()但它不在那里。该功能似乎在boostulp中可用。
我可以自己编写一些代码,但我更愿意使用标准化代码(如果有的话)。我错过了文档中的某些内容吗?
编辑:为了更清楚地说明,我正在谈论浮点数的指数的计算,而不是浮点数格式(类型)x的获取min_或max_指数范围。
我读过一些主题,这些主题已经分解了双打并“将其组合在一起”,但我正在尝试将其分解为基本组件。到目前为止,我已经确定了这一点:
breakDouble( double d ){
long L = *(long*) &d;
sign;
long mask = 0x8000000000000000L;
if( (L & mask) == mask ){
sign = 1;
} else {
fps.sign = 0;
}
...
}
Run Code Online (Sandbox Code Playgroud)
但我对如何获得指数和尾数感到非常困惑。我成功地将双精度数强制转换为长整型,因为只有前导位很重要,因此截断不起作用。然而,对于其他部分,我认为这不起作用,而且我知道你不能对浮点数进行按位运算符,所以我陷入了困境。
想法?
编辑:当然,当我发布此内容时,我发现了这一点,但我不确定在这种情况下浮点数和双精度数有多么不同。
编辑2(抱歉,我正在工作):我读了我在编辑1中链接的帖子,在我看来,我可以以同样的方式执行他们在我的双倍上执行的操作,指数的掩码是:
mask = 0x7FF0000000000000L;
Run Code Online (Sandbox Code Playgroud)
对于尾数:
mask = 0xFFFFFFFFFFFFFL;
Run Code Online (Sandbox Code Playgroud)
它是否正确?
我看到了函数double frexp (double x, int* exp);,它将一个double分为尾数(m)和指数(e),幂为2(1.m * 2^e).是否有类似的函数以10的幂返回值?像是m * 10^e完美的东西.
我正在尝试找到一种方法来检查浮点数是否为负而不分支。
float a = -0.5;
int getSignOfa= *(int*)&a >> 31; //type-pun to int and get signed bit;
Run Code Online (Sandbox Code Playgroud)
这是检查浮点数有符号位的安全方法吗?