相关疑难解决方法(0)

将4元素字符数组复制为C中的整数

char是1个字节,整数是4个字节.我想逐字节地从char [4]复制到整数.我想到了不同的方法,但我得到了不同的答案.

char str[4]="abc";
unsigned int a = *(unsigned int*)str;
unsigned int b = str[0]<<24 | str[1]<<16 | str[2]<<8 | str[3];
unsigned int c;
memcpy(&c, str, 4);
printf("%u %u %u\n", a, b, c);
Run Code Online (Sandbox Code Playgroud)

输出为6513249 1633837824 6513249

哪一个是正确的?出了什么问题?

c

9
推荐指数
2
解决办法
8643
查看次数

将uint32_t转换为int32_t,不会有溢出或过度复杂的风险

我怎样才能最好地转换uint32_tint32_t快速地与包装,在C++?

一些尝试:

uint32_t y = UINT32_MAX;
int32_t x = (int32_t)y; // UB on overflow
int32_t x = *(int32_t*)&y; // does this violate strict aliasing?
Run Code Online (Sandbox Code Playgroud)

c++ undefined-behavior

8
推荐指数
2
解决办法
3528
查看次数

将字节数组转换为float

我有一个程序需要占用4个字节并将它们转换为IEEE-754浮点数.字节不按顺序传输,但我可以把它们按顺序放回去.我的问题是把它们扔到浮子上.代码的相关部分:

//Union to store bytes and float on top of each other
typedef union {
    unsigned char b[4];
    float f;
} bfloat;

//Create instance of the union
bfloat Temperature;

//Add float data using transmitted bytes
MMI.Temperature.b[2] = 0xD1;//MMIResponseMsg[7];
MMI.Temperature.b[3] = 0xE1;//MMIResponseMsg[8];
MMI.Temperature.b[0] = 0x41;//MMIResponseMsg[9];
MMI.Temperature.b[1] = 0xD7;//MMIResponseMsg[10];

//Attempting to read the float value
lWhole=(long) ((float)MMI.Temperature.f);
//DEBUGGING
stevenFloat = (float)MMI.Temperature.f;
Run Code Online (Sandbox Code Playgroud)

lWhole很长,stevenFloat是一个漂浮.当调试我可以看到,我分配给字节数组中的值被正确地存储,然而的值stevenFloatlWhole不正确.它们似乎悬停在接近0或接近最大浮点数/长值的位置.使用我的编译器,long和float都是32位.

有谁知道为什么这不起作用?当我收到要处理的代码时看起来对我来说是正确的,它似乎是一个在线的常见解决方案,我只是难倒.

c c++ casting

7
推荐指数
1
解决办法
6600
查看次数

C++中非常快速的近似Logarithm(自然日志)函数?

我们发现要替换的各种技巧std::sqrt(Timing Square Root)和一些std::exp(使用更快的指数近似),但我找不到任何可替代的东西std::log.

它是我程序中循环的一部分,它被多次调用,而exp和sqrt被优化,英特尔VTune现在建议我进行优化std::log,之后似乎只有我的设计选择才会受到限制.

现在我使用的第三阶泰勒近似ln(1+x)x之间-0.5+0.5(对于4%最大误差的情况下的%90)和回退到std::log否则.这让我加速了15%.

c++ math logarithm micro-optimization sqrt

7
推荐指数
1
解决办法
7488
查看次数

将float序列化为32位整数的便携方式

我一直在努力寻找一种可移植的方法来序列化C和C++中的32位浮点变量,以便发送到微控制器和从微控制器发送.我希望格式足够明确,以便可以从其他语言完成序列化/反序列化,而无需太多努力.相关问题是:

C++中双/浮点型二进制序列化的可移植性

用C序列化double和float

c ++便携式转换为long to double

我知道在大多数情况下,类型转换联合/ memcpy可以正常工作,因为浮动表示是相同的,但我宁愿有更多的控制和心灵.到目前为止我想出的是以下内容:

void serialize_float32(uint8_t* buffer, float number, int32_t *index) {
    int e = 0;
    float sig = frexpf(number, &e);
    float sig_abs = fabsf(sig);
    uint32_t sig_i = 0;

    if (sig_abs >= 0.5) {
        sig_i = (uint32_t)((sig_abs - 0.5f) * 2.0f * 8388608.0f);
        e += 126;
    }

    uint32_t res = ((e & 0xFF) << 23) | (sig_i & 0x7FFFFF);
    if (sig < 0) {
        res |= 1 << 31;
    }

    buffer[(*index)++] = (res …
Run Code Online (Sandbox Code Playgroud)

c c++ embedded floating-point

7
推荐指数
2
解决办法
1086
查看次数

在union中使用char数组

我能够打印出int的地址和值,但不能打印出union的字符.为什么会这样

#include <iostream>

using namespace std;

union Endian
{
    int i;
    char c[sizeof(int)];
    int j;
};

int main(int argc, char *argv[]) {
    Endian e;
    e.i = 20;
    cout << &e.j;
    cout << &e.i;
    cout << &e.c[0]; //Why can't I print this address
    cout << e.c[1]; // Why can't I print this value

}
Run Code Online (Sandbox Code Playgroud)

O/P:0x7fff5451ab68 0x7fff5451ab68

c++

6
推荐指数
1
解决办法
1万
查看次数

ARM Neon:如何将uint8x16_t转换为uint8x8x2_t?

我最近发现了vreinterpret {q} _dsttype_srctype转换运算符.但是,这似乎不支持此链接(页面底部)中描述的数据类型的转换:

一些内在函数使用以下形式的向量类型数组:

<type><size>x<number of lanes>x<length of array>_t

这些类型被视为包含名为val的单个元素的普通C结构.

示例结构定义是:

struct int16x4x2_t    
{
    int16x4_t val[2];     
};
Run Code Online (Sandbox Code Playgroud)

你知道如何转换uint8x16_tuint8x8x2_t

请注意,使用union无法可靠地解决问题(从非活动成员读取导致未定义的行为编辑:这只是C++的情况,而事实证明C允许类型惩罚),也没有使用指针来强制转换(打破严格别名规则).

c c++ arm vectorization neon

6
推荐指数
2
解决办法
1682
查看次数

使用(float&)int工作类型punning,(float const&)int转换为(float)int而不是?

VS2019,发布,x86.

template <int i> float get() const {
    int f = _mm_extract_ps(fmm, i);
    return (float const&)f;
}
Run Code Online (Sandbox Code Playgroud)

使用return (float&)f;编译器时使用

extractps m32, ...
movss xmm0, m32
Run Code Online (Sandbox Code Playgroud)

.正确的结果

使用return (float const&)f;编译器时使用

extractps eax, ...
movd xmm0, eax
Run Code Online (Sandbox Code Playgroud)

.错误的结果

T&和T const&首先是T然后是const的主要思想.Const只是程序员的某种协议.你知道你可以解决它.但汇编代码中没有任何const,但是类型为float IS.我认为对于float和float const而言它必须是汇编中的浮点表示(cpu寄存器).我们可以使用中间int reg32,但最终解释必须是float.

而此时它看起来像回归,因为这之前工作正常.并且在这种情况下使用float也绝对是奇怪的,因为我们不应该考虑浮动const和安全性而是浮动的临时变量并且确实值得怀疑.

微软回答:

嗨Truthfinder,感谢自成一体的复制品.碰巧,这种行为实际上是正确的.正如我的同事@Xiang Fan [MSFT]在内部电子邮件中所述:

由[a c-style cast]执行的转换尝试以下序列:(4.1) - const_cast(7.6.1.11),(4.2) - static_cast(7.6.1.9),(4.3) - static_cast后跟const_cast ,(4.4) - reinterpret_cast(7.6.1.10)或(4.5) - reinterpret_cast后跟const_cast,

如果转换可以用上面列出的多种方式解释,则使用列表中首先出现的解释.

所以在你的情况下,(const float&)被转换为static_cast,其效果是"初始化表达式被隐式转换为类型为"cv1 T1"的prvalue.应用临时实现转换并将引用绑定到结果".

但在另一种情况下,(float&)被转换为reinterpret_cast,因为static_cast无效,这与reinterpret_cast(&operand)相同.

您正在观察的实际"错误"是一个强制转换:"将浮点型值"1.0"转换为等效的int-typed值"1"",而另一个强制转换说"将1.0的位表示形式转换为一个浮点数,然后将这些位解释为int".

出于这个原因,我们建议不要使用c风格的演员表.

谢谢!

MS论坛链接:https://developercommunity.visualstudio.com/content/problem/411552/extract-ps-intrinsics-bug.html

有任何想法吗?

PS我真正想要的是什么:

float val …
Run Code Online (Sandbox Code Playgroud)

c++ assembly sse intrinsics visual-c++

6
推荐指数
2
解决办法
299
查看次数

你能以与字节无关的方式获得指向低位字节的指针吗?

我有一个16位变量data,即:

volatile uint16_t data;
Run Code Online (Sandbox Code Playgroud)

我需要根据外部传感器上两个8位寄存器的内容填充该值.这些通过I2C/TWI访问.

我的TWI例程是async*,并且有签名:

bool twi_read_register(uint8_t sla, uint8_t reg, uint8_t *data, void (*callback)(void));
Run Code Online (Sandbox Code Playgroud)

这读取的价值regsla*data,然后调用callback().

如果我知道它uint16_t被安排在记忆中,比如说MSB LSB,那么我可以这样做:

twi_read_register(SLA, REG_MSB, (uint8_t *)&data, NULL);
twi_read_register(SLA, REG_LSB, (uint8_t *)&data + 1, NULL);
Run Code Online (Sandbox Code Playgroud)

但是,我不喜欢将endian依赖到我的代码中.有没有办法以与endian无关的方式实现这一目标?

(旁注:我目前的实际解决方法是使用结构,即:

typedef struct {
    uint8_t msb;
    uint8_t lsb;
} SensorReading;
Run Code Online (Sandbox Code Playgroud)

但我很好奇,如果我能用一个简单的方法做到这一点uint16_t)

编辑

(*async我的意思是分裂阶段,*data即将在未来的某个时间点设置,此时callback如果请求,将通过函数通知被调用者)

c embedded endianness

5
推荐指数
1
解决办法
467
查看次数

union for uint32_t和uint8_t [4]未定义的行为?

这个答案的评论中,据说使用如下的联合将整数分割成它们的字节将是未定义的行为.在那个地方给出的代码是相似的,虽然与此不相同,请注意我是否更改了代码的未定义行为相关方面.

union addr {
 uint8_t addr8[4];
 uint32_t addr32;
};
Run Code Online (Sandbox Code Playgroud)

到目前为止,我认为这将是一个很好的做法,addr = {127, 0, 0, 1};并得到相应 uint32_t的回报.(我承认根据我的系统的字节顺序,这可能产生不同的结果.但问题仍然存在.)

这是未定义的行为吗?如果是这样,为什么?(我不知道C++中的UB是什么意思是访问非活动的联盟成员.)


C99

  • 在这一点上,C99非常接近C++ 03.

C++ 03

  • 在联合中,最多一个数据成员可以在任何时间处于活动状态,也就是说,最多一个数据成员的值可以随时存储在并集中.C++ 03,第9.5(1)节,第162页

然而

  • 如果POD-union包含几个共享一个共同初始序列的POD结构,则允许检查任何POD结构成员的公共初始序列同上.
  • 如果两个POD-struct类型具有相同数量的非静态数据成员,则它们是布局兼容的,并且相应的非静态数据成员(按顺序)具有布局兼容类型 C++ 03,第9.2(14)节,第157页
  • 如果两种类型T1和T2是相同类型,则T1和T2是布局兼容类型.C++ 03,第3.9(11)节,第53页

结论

  • as uint8_t[4]uint32_t不是同一类型(我猜,一个严格的混叠的东西)(加上两个都不是POD结构/联合)上面确实是UB?

C++ 11

  • 请注意,聚合类型不包含联合类型,因为具有联合类型的对象一次只能包含一个成员.C++ 11,脚注46,第42页

c c++ strict-aliasing unions type-punning

4
推荐指数
4
解决办法
3142
查看次数