相关疑难解决方法(0)

C中的严格别名

关于类型双关语的问题:为什么这段代码会破坏严格的别名规则:

int main()
{
    int a = 1;
    short j;

    printf("%i\n", j = *((short*)&a));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这不是:

int main()
{
    int a = 1;
    short j;
    int *p; 

    p=&a;
    printf("%i\n", j = *((short*)p));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

建设者gcc -fstrict-aliasing.

谢谢!

c gcc strict-aliasing

8
推荐指数
1
解决办法
586
查看次数

如何获取浮点字节?

我正在使用HIDAPI将一些数据发送到USB设备.这个数据只能作为字节数组发送,我需要在这个数据数组中发送一些浮点数.我知道浮点数有4个字节所以我认为这可能有用:

float f = 0.6;
char data[4];

data[0] = (int) f >> 24;
data[1] = (int) f >> 16;
data[2] = (int) f >> 8;
data[3] = (int) f;
Run Code Online (Sandbox Code Playgroud)

后来我所要做的就是:

g = (float)((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]) );
Run Code Online (Sandbox Code Playgroud)

但测试这一点告诉我,像float返回的线总是4.我的代码出了什么问题,我怎么能正确地做到这一点(即在4个字节字节中打破浮点内部数据并在以后重建同一个浮点数)?

编辑:

我能够用以下代码完成此任务:

float f = 0.1;
unsigned char *pc;
pc = (unsigned char*)&f;

// 0.6 in float
pc[0] = 0x9A;
pc[1] = 0x99;
pc[2] = 0x19;
pc[3] = 0x3F; …
Run Code Online (Sandbox Code Playgroud)

c floating-point

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

C++中是否有完整的Implementation-Defined行为列表?

我回答了对我的回答的评论:C求职面试 - 演员和比较,发现我找不到C++认为"实施定义行为"的完整列表.我知道这类事情有3个类别:未定义的行为,实现定义的行为和未指定的行为; 然而,似乎大多数讨论都围绕未定义的行为,并且当讨论实现定义的行为时,最多给出一个例子.一般来说,我倾向于编写很多代码来捕获这个区域,我知道会发生什么样的行为; 我仍然希望能够对其有效性发表评论.我还想抛弃那里,我认为操作社区中有很多误诊是未定义的,而实际上它们是由平台很好地定义的.

请注意,我对给定平台如何选择定义此类行为并不感兴趣,而是对包含C++标准定义的"实现定义"类别中的所有行为的列表感兴趣.

c++ standards

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

取消引用类型双关指针将破坏严格别名规则:字节数组到数字

我已经阅读了许多有关此警告的问题(取消引用类型双关指针会破坏严格别名规则取消引用类型双关指针会破坏严格别名规则 [-Wstrict-aliasing]严格别名规则是什么?“取消引用类型双关指针将破坏严格的别名规则”警告和其他人)并且对我的警告完全感到困惑。

所以我有一个结构:

typedef struct {
    unsigned char precision;
    unsigned char scale;
    unsigned char array[33];
} DBNUMERIC;
Run Code Online (Sandbox Code Playgroud)

当从 MS SQL Server 检索数据时,该结构由 FreeTDS 库填充。我知道从array[1]那里开始是 64 位整数(大端),我想得到它。我使用以下代码:

int64_t result = 0;
result = be64toh(*((decltype(result)*)(numeric.array + 1)));
Run Code Online (Sandbox Code Playgroud)

但是 GCC 给了我警告dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]。但是如果我使用代码:

int64_t result = 0;
decltype(result)* temp_ptr = (decltype(result)*)(numeric.array + 1);
decltype(result) temp = *temp_ptr;
result = be64toh(temp);
Run Code Online (Sandbox Code Playgroud)

没有关于违反严格别名规则的警告。我不认为此代码与原始代码不同,因此我很困惑。如何将数组中的 8 个字节转换为int64_t变量?

c++ gcc strict-aliasing gcc-warning

3
推荐指数
1
解决办法
850
查看次数

将unsigned char数组解释为bool数组

请考虑以下代码.它没问题还是会导致未定义的行为?

#include <iostream>

int main()
{
    {
        unsigned char binary[] = {0, 5, 10};
        bool* x = reinterpret_cast<bool*>(&binary[0]);

        for (unsigned int i = 0; i < 3; ++i)
        {
            std::cout << (x[i] ? 1 : 0) << " ";
        }
    }

    {
        unsigned char b = 255;
        bool* x = reinterpret_cast<bool*>(&b);
        std::cout << (*x ? 1 : 0) << std::endl;
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用gcc 4.6到4.8编译时的输出是

0 5 10 1

但只有优化(-O1和更多).Clang导致

0 1 1 1

即使有优化.现在,如果更改y[i] ? …

c++ gcc casting boolean

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

什么时候可以做/使用具有未指定行为的东西?

在C++中,有些东西出现在明确定义和未定义之间.具体而言,这些被称为实现定义未指定.现在,我对未指明的东西很感兴趣.

什么时候可以使用这些功能,什么时候应该避免?是否有正确代码的未指定行为的良好示例?在编写软件时,它是否是最佳选择?

Matt McNabb提供的定义:

  • 未定义 - 任何事情都可能发生

  • 实现定义 - 有限数量的结果是可能的,编译器的文档必须说明会发生什么

  • 未指定 - 可能有限数量的结果 - 通常标准描述了可能结果的集合

  • 定义明确 - 以上都不是

  • 格式良好的程序 - 无错误编译的程序(可能表现出未定义的行为)

后续问题:

放松的原子是否被指定为未指定或明确定义?

标记为从不同角度谈论相同想法的问题的副本.标记为同样的问题涉及未指明行为的定义,而这里的问题是关于如何以及何时使用它.

c++ undefined-behavior unspecified-behavior relaxed-atomics

-2
推荐指数
1
解决办法
203
查看次数