C位字段变量打印意外的值 [英] C bit field variables are printing unexpected values

查看:141
本文介绍了C位字段变量打印意外的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

struct m

{
   int parent:3;

   int child:3;

   int mother:2;
};

void main()
{

   struct m son={2,-6,5};

   printf("%d %d %d",son.parent,son.child,son.mother);
}

任何人能请告诉帮忙为什么程序的输出 2 2 1

推荐答案

取出所有的但显示的字段显著位:

Taking out all but the significant bits for the fields shown:

parent: 3 bits (1-sign bit + 2 more), value 010, result 2
child:  3 bits (1-sign bit + 2 more), value 010, result 2
mother: 2 bits (1 sign bit + 1 more), value  01, result 1


详细信息

这值得指出的是,你的结构字段声明为 INT 位字段值。通过C99-§6.7.2,2,以下类型都是等价的: INT 签署符号int 。因此,您的结构字段的签署的。通过C99-§6.2.6.2,2,你的点点之一应在重新presenting的变量(正或负)的符号被消费。此外,这不包括符号位,其余位重新presentation相同部分国家必须对应于相关的符号的类型,其余位计数。 C99-§6.7.2,1清楚地定义了每个这些位的重新presents 2的幂。因此,通常被用作符号位的唯一位是最显著位(其是唯一一个剩下的,但我敢肯定,如果这是我听到它在适当的时间标准)的不准确际pretation。那你作为用于您的样品测试值之一分配负数表明你的可能的意识到这一点,但很多人刚刚接触位字段都没有。因此,它承担值得注意。

It bears pointing out that your structure fields are declared as int bit-field values. By C99-§6.7.2,2, the following types are all equivalent: int, signed, or signed int. Therefore, your structure fields are signed. By C99-§6.2.6.2,2, one of your bits shall be consumed in representing the "sign" of the variable (negative or positive). Further, the same section states that excluding the sign-bit, the remaining bits representation must correspond to an associated unsigned type of the remaining bit-count. C99-§6.7.2,1 clearly defines how each of these bits represents a power of 2. Therefore, the only bit that is normally used as the sign-bit is the most significant bit (its the only one that is left, but I'm quite sure if this is an inaccurate interpretation of the standard I'll hear about it in due time). That you are assigning a negative number as one of your test values used for your sample suggests you may be aware of this, but many people newly exposed to bit fields are not. Thus, it bears noting.

C99标准的以下章节在这个答案的其余部分被引用。与促销不同类型的第一个交易,未来估值和潜在价值变化(如果有的话)。最后是在理解如何位字段 INT 型的确定非常重要的。

The following sections of the C99 standard are referenced in the remainder of this answer. The first deals with promotions to different types, the next the valuation and potential value-change (if any). The last is important in understanding how a bit-fields int-type is determined.

C99-§6.3.1.1:布尔,字符和整数

2:如果 INT 可以重新present原始类型(如宽度的限制,对于一个位字段)的所有值,该值转换到 INT ;否则,将其转换为 unsigned int类型。这些被称为整数促销。所有其他类型是整数的提升不会改变。

2: If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.

C99-§6.3.1.3符号和无符号整数


      
  1. 当与整数类型的值被转换为比_Bool其他,另一整数类型,如果该值可再被新类型psented $ P $,这是不变的。

  2.   
  3. 否则,如果新类型是无符号的值被重复地增加或减少超过可重新在新类型psented $ P $直到该值是新类型的范围的最大值多一个转换

  4.   
  5. 否则,新的类型签名和值不能再次在它psented $ P $;无论结果是实现定义或实现定义的信号提高。

  6.   

C99-§6.7.2.1结构和联合说明

10:A 位域的PTED是具有由位的指定数量的符号或无符号整数类型间$ P $。如果该值为0或1被存储到类型_Bool的非零宽度位字段,该位字段的值应比较等于存储的值;一个_Bool位字段有_Bool的语义。

10: A bit-field is interpreted as having a signed or unsigned integer type consisting of the specified number of bits. If the value 0 or 1 is stored into a nonzero-width bit-field of type _Bool, the value of the bit-field shall compare equal to the value stored; a _Bool bit-field has the semantics of a _Bool.

考虑到经常 INT 位重新$ P $测试值psentation。以下是在32位 INT 实施

Consider the regular int bit representation of your test values. The following are on a 32-bit int implementation:

value : s  bits 
    2 : 0  0000000 00000000 00000000 00000010   <== note bottom three bits
   -6 : 1  1111111 11111111 11111111 11111010   <== note bottom three bits
    5 : 0  0000000 00000000 00000000 00000101   <== note bottom two bits

通过每个这些步行,从上面的标准参考施加的要求。

Walking through each of these, applying the requirements from the standard references above.

INT父:3 :第一个字段是3位有符号 INT ,并正在分配十进制值 2 。请问右值类型, INT ,包括左值类型, INT:3 ?是的,所以类型是不错的。请问的 2 左值类型的范围内配合?好吧, 2 ,可以轻松适应在 INT:3 ,所以没有价值碴要么是必需的。第一场正常工作。

int parent:3 :The first field is a 3-bit signed int, and is being assigned the decimal value 2. Does the rvalue type, int, encompass the lvalue type, int:3? Yes, so the types are good. Does the value 2 fit within the range of the lvalue type? Well, 2 can easily fit in an int:3, so no value mucking is required either. The first field works fine.

INT孩子:3 :第二场也有3位有符号 INT ,这次被分配十进制值 -6 。再次,做右值类型( INT )的全包围式左值( INT:3 )?是的,所以再次类型是罚款。但是,最小的位计数需要重新present -6 ,一个符号值,为 4 位。 ( 1010 ),占最signnificant位为符号位。因此,值 -6 超出3位有符号位域的允许的存储范围。因此,结果是实现定义的每§6.3.1.3-3。

int child:3: The second field is also a 3-bit signed int, this time being assigned the decimal value -6. Once again, does the rvalue type (int) fully-encompass the lvalue type (int:3)? Yes, so again the types are fine. However, the minimum bit-count require to represent -6, a signed value, is 4 bits. (1010), accounting for the most signnificant bit as the sign-bit. Therefore the value -6 is out of range of the allowable storage of a 3-bit signed bit-field. Therefore, the result is implementation-defined per §6.3.1.3-3.

INT母亲:2 最后一个字段是一个2位有符号 INT 这次被分配十进制值5.再次,它的右值类型( INT )的全包围式左值( INT:2 )?是的,所以再次类型是罚款。但是,再一次我们面临着不能适合目标类型内的值。最低位计数需要重新presenting一个的签署的正 5 为四种:(0101)。我们只有两个一起工作。因此,其结果是再次实现定义的每§6.3.1.3-3

int mother:2 The final field is a 2-bit signed int, this time being assigned the decimal value 5. Once again, does the rvalue type (int) fully-encompass the lvalue type (int:2)? Yes, so again the types are fine. However, once again we're faced with a value that cannot fit within the target-type. The minimum bit-count need for representing a signed positive 5 is four: (0101). We only have two to work with. Therefore, the result is once again implementation-defined per §6.3.1.3-3.

因此​​,如果我借此正确地,在这种情况下,实现仅仅黑客关闭所有未存储所需要的所需要的比特填充声明位深度。而这两轮牛车的结果是什么,你现在有。 2 2 1

Therefore, if I take this correctly, the implementation in this case simply hacks off all but the required bits needed to store fill the declared bit depth. And the results of that hackery is what you now have. 2 2 1

注意

这是完全有可能我翻转推广的顺序不正确(很容易让我迷失在标准的,因为我诵读困难,并定期翻转在我脑海中的东西)。如果是这样的情况下,我会问任何人的标准有更强的跨pretation请指出这一点给我的,我会相应地解决问题的答案。

It is entirely possible I flipped the order of the promotion incorrectly (it is easy for me to get lost in the standard, as I am dyslexic and flip things in my head periodically). If that is the case I would ask anyone with a stronger interpretation of the standard please point this out to me an I will address the answer accordingly.

这篇关于C位字段变量打印意外的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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