解引用类型punned指针将打破严格走样规则 [英] Dereferencing type-punned pointer will break strict-aliasing rules

查看:149
本文介绍了解引用类型punned指针将打破严格走样规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用下面这段code,以从文件中读取数据作为一个更大的计划的一部分。

I used the following piece of code to read data from files as part of a larger program.

double data_read(FILE *stream,int code) {
        char data[8];
        switch(code) {
        case 0x08:
            return (unsigned char)fgetc(stream);
        case 0x09:
            return (signed char)fgetc(stream);
        case 0x0b:
            data[1] = fgetc(stream);
            data[0] = fgetc(stream);
            return *(short*)data;
        case 0x0c:
            for(int i=3;i>=0;i--)
                data[i] = fgetc(stream);
            return *(int*)data;
        case 0x0d:
            for(int i=3;i>=0;i--)
                data[i] = fgetc(stream);
            return *(float*)data;
        case 0x0e:
            for(int i=7;i>=0;i--)
                data[i] = fgetc(stream);
            return *(double*)data;
        }
        die("data read failed");
        return 1;
    }

现在有人告诉我使用 -O2 和我获得以下的gcc的警告:
警告:提领型punned指针将打破严格走样规则

Now I am told to use -O2 and I get following gcc warning: warning: dereferencing type-punned pointer will break strict-aliasing rules

Googleing我发现了两个正交的答案:

Googleing I found two orthogonal answers:

VS

  • So basically if you have an int* and a float* they are not allowed to point to the same memory location. If your code does not respect this, then the compiler's optimizer will most likely break your code.

在最后,我不想忽略警告。你有什么建议?

In the end I don't want to ignore the warnings. What would you recommend?

[更新] 我取代玩具例子与实际功能。

[update] I substituted the toy example with the real function.

推荐答案

看起来很多,如果你真的想用FREAD:

It looks a lot as if you really want to use fread:

int data;
fread(&data, sizeof(data), 1, stream);

这是说,如果你想去读字符的路线,然后reinter preting他们作为一个int,安全的方式做到这一点在C(但不可以在C ++中)是使用工会:

That said, if you do want to go the route of reading chars, then reinterpreting them as an int, the safe way to do it in C (but not in C++) is to use a union:

union
{
    char theChars[4];
    int theInt;
} myunion;

for(int i=0; i<4; i++)
    myunion.theChars[i] = fgetc(stream);
return myunion.theInt;

我不知道为什么数据在你原来的code的长度是3。我想你想的4个字节;至少我不知道在哪里的int是3个字节的任何系统。

I'm not sure why the length of data in your original code is 3. I assume you wanted 4 bytes; at least I don't know of any systems where an int is 3 bytes.

请注意,无论您的code和我的是高度不可移植。

Note that both your code and mine are highly non-portable.

编辑:如果您想从文件中读取各种长度的整数,可移植,尝试这样的事情:

If you want to read ints of various lengths from a file, portably, try something like this:

unsigned result=0;
for(int i=0; i<4; i++)
    result = (result << 8) | fgetc(stream);

(注:在实际的程序,你还想要测试龟etc()对EOF的返回值)

(Note: In a real program, you would additionally want to test the return value of fgetc() against EOF.)

这读取小尾数格式的4字节从文件签名,的无论的是什么系统的字节顺序是。它可以工作在几乎所有的系统,其中一个无符号至少为4个字节。

This reads a 4-byte unsigned from the file in little-endian format, regardless of what the endianness of the system is. It should work on just about any system where an unsigned is at least 4 bytes.

如果你想成为尾数中立的,不使用指针或工会;使用位变化来代替。

If you want to be endian-neutral, don't use pointers or unions; use bit-shifts instead.

这篇关于解引用类型punned指针将打破严格走样规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆