便携式数据reinter pretation [英] Portable data reinterpretation

查看:150
本文介绍了便携式数据reinter pretation的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

欲reinter一种类型的$ P $角数据作为在便携式方式(C99)另一种类型。
我的的谈论铸造,我要的 reinter pretation 的某些给定的数据。
此外,通过的移动的我的意思是它不会破坏C99规则 - 我做的的意味reinter pretated值是在所有系统上平等

我知道3种不同的方式来reinter preT的数据,但只有其中两个是便携式的:


  1. 这是不可移植的 - 它打破了严格别名规则

      / *#1类型双关* /浮float_value = 3.14;
    为int * int_pointer =(INT *)及float_value;
    INT int_value = * int_pointer;


  2. 这是依赖于平台,因为它写浮动后读取来自工会的 INT 进去。但它不会破坏任何C99规则,所以应该工作(如的sizeof(int)的==的sizeof(浮动))。

      / *#2联合双关* /联合数据{
      浮float_value;
      INT int_value;
    };联合数据data_value;
    data_value.float_value = 3.14;
    INT int_value = data_value.int_value;


  3. 应该是罚款,只要的sizeof(int)的==的sizeof(浮动)

      / *#3 *复制/浮float_value = 3.14;
    INT int_value = 0;
    的memcpy(安培; int_value,&安培; float_value,sizeof的(int_value));


我的问题:


  1. 这是正确的?

  2. 你知道其他方式在移动的办法reinter preT的数据?


解决方案

解决方案2的的便携 - 通过工会型双关的C99一直是合法的,并且它作出了明确与TC3,它增加下面的脚注部分6.5.2.3:


  

如果用于访问一个联合对象的内容的部件是不
  相同构件最后用于存储在对象的值,则
  值的对象重新presentation的适当部分是
  reinter PTED作为新类型的对象重新presentation $ P $所描述
  在6.2.6(一个有时被称为类型双关语处理)。这可能是一个
  陷阱重新presentation。


附件J仍然将其列为unspecfie​​d行为,这是一个已知缺陷和C11,改变已得到纠正。


  

工会成员比存入最后一个其他值[未指定的]



  

字节对应比去年储存在另外一个工会成员的值
  进入[未指定的]


这不是什么大不了的事作为附件只是信息,不规范的。

请记住,你仍然可以结束了不确定的行为,如:


  • 通过创建一个陷阱重新presentation

  • 将与指针类型成员的情况下,违反别名规则
  • (这应该不是通过类型夯实无论如何,因为不需要一个统一的指针再presentation被转换)
  • ,如果联合成员具有不同的尺寸 - 仅在商店上次使用的构件的字节已指定的值;特别是在更小的部件存储值也可以无效尾随一个较大部件的字节

  • 如果一个成员包含填充字节,它始终以未指定的值

I want to reinterpret data of one type as another type in a portable way (C99). I am not talking about casting, I want a reinterpretation of some given data. Also, by portable I mean that it does not break C99 rules - I do not mean that the reinterpretated value is equal on all systems.

I know 3 different way to reinterpret data, but only two of these are portable:

  1. This is not portable - it breaks the strict aliasing rule.

    /* #1 Type Punning */
    
    float float_value = 3.14;
    int *int_pointer = (int *)&float_value;
    int int_value = *int_pointer;
    

  2. This is platform dependent, because it reads an int value from the union after writing a float into it. But it does not break any C99 rules, so that should work (if sizeof(int) == sizeof(float)).

    /* #2 Union Punning */
    
    union data {
      float float_value;
      int int_value;
    };
    
    union data data_value;
    data_value.float_value = 3.14;
    int int_value = data_value.int_value;
    

  3. Should be fine, as long as sizeof(int) == sizeof(float)

    /* #3 Copying */
    
    float float_value = 3.14;
    int int_value = 0;
    memcpy(&int_value, &float_value, sizeof(int_value));
    

My Questions:

  1. Is this correct?
  2. Do you know other ways to reinterpret data in a portable way?

解决方案

Solution 2 is portable - type punning through unions has always been legal in C99, and it was made explicit with TC3, which added the following footnote to section 6.5.2.3:

If the member used to access the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called "type punning"). This might be a trap representation.

Annex J still lists it as unspecfied behaviour, which is a known defect and has been corrected with C11, which changed

The value of a union member other than the last one stored into [is unspecified]

to

The values of bytes that correspond to union members other than the one last stored into [are unspecified]

It's not that big a deal as the annex is only informative, not normative.

Keep in mind that you can still end up with undefined behaviour, eg

  • by creating a trap representation
  • by violating aliasing rules in case of members with pointer type (which should not be converted via type-punning anyway as there need not be a uniform pointer representation)
  • if the union members have different sizes - only the bytes of the member last used in a store have specified value; in particular, storing values in a smaller member can also invalidate trailing bytes of a larger member
  • if a member contains padding bytes, which always take unspecified values

这篇关于便携式数据reinter pretation的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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