相关疑难解决方法(0)

我应该担心指针投射过程中的对齐吗?

在我的项目中,我们有一段这样的代码:

// raw data consists of 4 ints
unsigned char data[16];
int i1, i2, i3, i4;
i1 = *((int*)data);
i2 = *((int*)(data + 4));
i3 = *((int*)(data + 8));
i4 = *((int*)(data + 12));
Run Code Online (Sandbox Code Playgroud)

我和我的技术负责人谈到这个代码可能不便携,因为它试图将a unsigned char*转换为int*通常具有更严格的对齐要求的代码.但是技术主管说没关系,大多数编译器在转换后仍保持相同的指针值,我可以像这样编写代码.

坦率地说,我并不是真的相信.经过研究,我发现有些人反对使用上面的指针铸件,例如,这里这里.

所以这是我的问题:

  1. 在真实项目中投射后取消引用指针真的很安全吗?
  2. C型铸造和reinterpret_cast?之间有什么区别吗?
  3. C和C++之间有什么区别吗?

c c++ casting alignment

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

使用std :: ofstream二进制写入时出现意外结果

我是C++ std :: stream的新手,我正在做一些测试.我有这个简单的代码:

int i = 10;
char c = 'c';
float f = 30.40f;

std::ofstream out("test.txt", std::ios::binary | std::ios::out);
if(out.is_open())
{
    out<<i<<c<<f;
    out.close();
}
Run Code Online (Sandbox Code Playgroud)

正如std::ios::binary我在test.txt文件中所期望的那样打开流以具有二进制表示形式i,c并且f,但是我有10c30.4.

你能告诉我我做错了什么吗?

c++ iostream

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

C++的新操作是否保证地址返回的对齐?

大多数有经验的程序员都知道数据对齐对于程序的性能很重要.我看到一些程序员编写的程序分配比他们需要的更大的缓冲区大小,并使用对齐的指针作为开始.我想知道我应该在我的程序中这样做,我不知道是否有任何保证C++的新操作返回的地址对齐.所以我写了一个小程序来测试

for(size_t i = 0; i < 100; ++i) {
    char *p = new char[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
    short *p = new short[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout << "*";
        system("pause");
    }
    cout << reinterpret_cast<void *>(p) << endl;
}
for(size_t i = 0; i < 100; ++i) {
    float *p = new float[123];
    if(reinterpret_cast<size_t>(p) % 4) {
        cout …
Run Code Online (Sandbox Code Playgroud)

c++ performance alignment new-operator

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

在C++ 11(或更高版本)中从字节数组反序列化对象的无定义行为方式是什么?

为了克服对齐问题,我需要记忆成一个临时的.临时的那种类型是什么?gcc抱怨以下reinterpret_cast将破坏严格的别名规则:

template <typename T>
T deserialize(char *ptr) {
    static_assert(std::is_trivially_copyable<T>::value, "must be trivially copyable");
    alignas(T) char raw[sizeof(T)];
    memcpy(raw, ptr, sizeof(T));
    return *reinterpret_cast<T *>(raw);
}
Run Code Online (Sandbox Code Playgroud)

(例如,当T为"长"时).

我不想定义T,因为我不想在覆盖之前构造T.

在一个联合中,不写一个成员然后读另一个计数作为未定义的行为?

template<typename T>
T deserialize(char *ptr) {
    union {
        char arr[sizeof(T)];
        T obj;
    } u;

    memcpy(u.arr, ptr, sizeof(T));   // Write to u.arr
    return u.obj;   // Read from u.obj, even though arr is the active member.
}
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing c++11

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

这是使用std :: array未定义的行为吗?

可能重复:
允许使用`char*`别名`T*`.是否也允许反过来?

我使用std::arraychars到持有未知的原始类型,这是不超过10个字节长,像这样的一个值:

std::array<char, 10> val;
*reinterpret_cast<double*>(val.data()) = 6.3;
//blah blah blah...
double stuff = *reinterpret_cast<double*>(val.data());
Run Code Online (Sandbox Code Playgroud)

我已经读过,来回转换char *并不是未定义的,因为编译器假设char *可以为任何类型的值设置别名.当值放在(我假设的)char对象内部的s 数组时,这仍然有效吗?

注意:我知道我可以在这里使用union,但这会导致我正在做的大量样板代码,并且我想在必要时避免它,因此问题.

c++ undefined-behavior c++11

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

在不破坏严格别名规则的情况下,在现代GCC/C++中使用网络缓冲区的正确方法

该计划 - 某种旧式网络消息传递:

// Common header for all network messages.
struct __attribute__((packed)) MsgHeader {
    uint32_t msgType;
};
// One of network messages.
struct __attribute__((packed)) Msg1 {
    MsgHeader header;
    uint32_t field1;
};

// Network receive buffer.
uint8_t rxBuffer[MAX_MSG_SIZE];

// Receive handler. The received message is already in the rxBuffer.
void onRxMessage() {
    // Detect message type
    if ( ((const MsgHeader*)rxBuffer)->msgType == MESSAGE1 ) { // Breaks strict-aliasing!
        // Process Msg1 message.
        const Msg1* msg1 = (const Msg1*)rxBuffer;
        if ( msg1->field1 == …
Run Code Online (Sandbox Code Playgroud)

c++ gcc strict-aliasing c++11

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

使用memcpy将int复制到char数组中然后打印其成员:未定义的行为?

请考虑以下代码:

int i = 1;
char c[sizeof (i)];
memcpy(c, &i, sizeof (i));
cout << static_cast<int>(c[0]);
Run Code Online (Sandbox Code Playgroud)

请忽略这是否是好代码.我知道输出取决于系统的字节顺序.这只是一个学术问题.

这段代码是:

  • 未定义的行为
  • 实现定义的行为
  • 定义明确的行为
  • 还有别的

c++ language-lawyer

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

在C ++中序列化二进制数据的正确方法

在阅读了下面的12 Q / As并在带有GCC和MSVC的x86架构上使用了下面讨论的技术多年之后,没有看到问题,现在我对应该是正确的东西感到非常困惑,但是这也是使用C ++进行序列化然后反序列化二进制数据的重要“最有效”方法。

给出以下“错误”代码:

int main()
{
   std::ifstream strm("file.bin");

   char buffer[sizeof(int)] = {0};

   strm.read(buffer,sizeof(int));

   int i = 0;

   // Experts seem to think doing the following is bad and
   // could crash entirely when run on ARM processors:
   i = reinterpret_cast<int*>(buffer); 

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

现在,据我所知,重新解释类型转换向编译器表明它可以将缓冲区中的内存视为整数,并且随后可以发出整数兼容指令,这些指令要求/假定所讨论的数据具有某些对齐方式-唯一的开销是当CPU检测到其试图执行面向对齐指令的地址实际上未对齐时,多余的读取和移位。

那就是说,上面提供的答案似乎表明,就C ++而言,这都是未定义的行为。

假定将从中进行强制转换的缓冲区位置的对齐方式不一致,那么,对于此问题,唯一的解决方案是将字节一乘一地复制吗?也许有一种更有效的技术?

此外,多年来,我已经看到很多情况,其中将完全由Pod组成的结构(使用特定于编译器的编译指示来删除填充)转换为char *,然后写入文件或套接字,然后再读回缓冲区并且将缓冲区转换回原始结构的指针(忽略机器之间的潜在字节序和浮点/双格式问题),这种代码是否也被视为未定义的行为?

以下是更复杂的示例:

int main()
{
   std::ifstream strm("file.bin");

   char buffer[1000] = {0};

   const std::size_t size = sizeof(int) + sizeof(short) + sizeof(float) + sizeof(double);

   const std::size_t weird_offset = …
Run Code Online (Sandbox Code Playgroud)

c c++ binary serialization undefined-behavior

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

我正在通过访问内存位置来更改const变量的值.为什么不起作用?

我试图理解c ++中的const.我在下面的代码片段中写了这个:

const int x=5;
int *ptr;
ptr=(int*)&x;
cout<<"address of x="<<&x<<endl;
cout<<"value of ptr="<<ptr<<endl;
*ptr=11;
cout<<"*ptr="<<*ptr<<endl;
cout<<"x="<<x;
Run Code Online (Sandbox Code Playgroud)

输出是

address of x=0x28fef8
address of ptr=0x28fef8
*ptr=11
x=5
Run Code Online (Sandbox Code Playgroud)

由于ptr指向x,我确信*ptr和x的值是相同的.为什么价值不同?我知道x是const,但是,我通过执行*ptr来改变内存地址的值.请告诉我我错过了什么.

c++ const

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

避免哈希函数中的严格别名冲突

如何避免严格别名规则违规,试图修改char*sha256函数的结果.

计算哈希值:

std::string sha = sha256("some text");
const char* sha_result = sha.c_str();
unsigned long* mod_args = reinterpret_cast<unsigned long*>(sha_result);
Run Code Online (Sandbox Code Playgroud)

得到2个64位:

unsigned long a = mod_args[1] ^ mod_args[3] ^ mod_args[5] ^ mod_args[7];
unsigned long b = mod_args[0] ^ mod_args[2] ^ mod_args[4] ^ mod_args[6]; 
Run Code Online (Sandbox Code Playgroud)

而不是通过concat获得结果两件:

unsigned long long result = (((unsigned long long)a) << 32) | b;
Run Code Online (Sandbox Code Playgroud)

c++ strict-aliasing

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