Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 枚举和无符号长位字段_C_Struct_Enums_Bit Fields - Fatal编程技术网

C 枚举和无符号长位字段

C 枚举和无符号长位字段,c,struct,enums,bit-fields,C,Struct,Enums,Bit Fields,如果我有以下带有枚举和无符号long的结构,填充是如何完成的?我相信编译器不会对var1和var2执行任何操作,因为它是32位且已填充的 typedef struct { unsigned long var1 : 8; unsigned long var2 : 24; my_enum var3 : 2; my_enum var4 : 2; } my_struct; var3和var4是否都有填充?例如,30位填充到var3和30位填充到v

如果我有以下带有枚举和无符号long的结构,填充是如何完成的?我相信编译器不会对
var1
var2
执行任何操作,因为它是32位且已填充的

typedef struct {
    unsigned long var1 : 8;
    unsigned long var2 : 24;
    my_enum var3       : 2;
    my_enum var4       : 2;
} my_struct;
var3
var4
是否都有填充?例如,30位填充到
var3
和30位填充到
var4
,或28位。我只是想了解位字段如何跨不同的数据类型和实现类型工作。

1。 位字段中使用的类型:

sizeof(my_struct)     = 8
sizeof(my_struct_var) = 8
Byte 0:  1 0 0 0 0 0 0 1 
Byte 1:  0 0 0 0 0 0 0 1 
Byte 2:  0 0 0 0 0 0 0 0 
Byte 3:  1 0 0 0 0 0 0 0 
Byte 4:  0 0 0 0 1 1 1 0 
Byte 5:  0 0 0 0 0 0 0 0 
Byte 6:  0 0 0 0 0 0 0 0 
Byte 7:  0 0 0 0 0 0 0 0 
#include <stdio.h>
#include <limits.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

typedef enum { ONE, TWO, THREE } my_enum;

typedef struct
{
   unsigned long var1 : 8;
   unsigned long var2 : 24;
   my_enum       var3 : 2;
   my_enum       var4 : 2;
} my_struct;

int main(void)
{
   int idx;
   int bitIdx;
   my_struct my_struct_var;

   memset (&my_struct_var,
           0,
           sizeof(my_struct_var));

   printf("sizeof(my_struct)     = %lu\n", sizeof(my_struct));
   printf("sizeof(my_struct_var) = %lu\n", sizeof(my_struct_var));

   my_struct_var.var1 = 0x81;     /* 1000 0001                     */
   my_struct_var.var2 = 0x800001; /* 1000 0000 0000 0000 0000 0001 */
   my_struct_var.var3 = 0b10;     /* 10                            */
   my_struct_var.var4 = 0b11;     /* 11                            */

   for (idx = 0; idx < sizeof(my_struct_var); ++idx)
   {
      char * curByte = &my_struct_var;
      curByte += idx;
      printf("\nByte %d:  ", idx);
      for (bitIdx = 0; bitIdx < CHAR_BIT; ++bitIdx)
      {
         printf("%c ", ((*curByte & (1 << ((CHAR_BIT - 1) - bitIdx))) >> ((CHAR_BIT - 1) - bitIdx)) + '0');
      }
   }

   return 0;
}
我只会在您的结构中使用
signed int
unsigned int
作为位字段类型。根据(6.7.2.1#4):

位字段的类型应为合格或不合格版本 \u Bool有符号整数无符号整数,或其他实现定义的类型

确保
无符号长
枚举类型
是实现定义的类型,但如果使用它们,则行为不可移植。您可以在两个不同的GCC版本中看到它:

根据手册:

  • 除_Bool、有符号整数和无符号整数(C99 6.7.2.1)以外的允许位字段类型
在严格一致的模式下,不允许使用其他类型

根据手册:

  • 除_Bool、有符号整数和无符号整数(C99和C116.7.2.1)以外的允许位字段类型
即使在严格一致的模式下,也允许使用其他整数类型,例如long int和枚举类型

2。 填充:

sizeof(my_struct)     = 8
sizeof(my_struct_var) = 8
Byte 0:  1 0 0 0 0 0 0 1 
Byte 1:  0 0 0 0 0 0 0 1 
Byte 2:  0 0 0 0 0 0 0 0 
Byte 3:  1 0 0 0 0 0 0 0 
Byte 4:  0 0 0 0 1 1 1 0 
Byte 5:  0 0 0 0 0 0 0 0 
Byte 6:  0 0 0 0 0 0 0 0 
Byte 7:  0 0 0 0 0 0 0 0 
#include <stdio.h>
#include <limits.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

typedef enum { ONE, TWO, THREE } my_enum;

typedef struct
{
   unsigned long var1 : 8;
   unsigned long var2 : 24;
   my_enum       var3 : 2;
   my_enum       var4 : 2;
} my_struct;

int main(void)
{
   int idx;
   int bitIdx;
   my_struct my_struct_var;

   memset (&my_struct_var,
           0,
           sizeof(my_struct_var));

   printf("sizeof(my_struct)     = %lu\n", sizeof(my_struct));
   printf("sizeof(my_struct_var) = %lu\n", sizeof(my_struct_var));

   my_struct_var.var1 = 0x81;     /* 1000 0001                     */
   my_struct_var.var2 = 0x800001; /* 1000 0000 0000 0000 0000 0001 */
   my_struct_var.var3 = 0b10;     /* 10                            */
   my_struct_var.var4 = 0b11;     /* 11                            */

   for (idx = 0; idx < sizeof(my_struct_var); ++idx)
   {
      char * curByte = &my_struct_var;
      curByte += idx;
      printf("\nByte %d:  ", idx);
      for (bitIdx = 0; bitIdx < CHAR_BIT; ++bitIdx)
      {
         printf("%c ", ((*curByte & (1 << ((CHAR_BIT - 1) - bitIdx))) >> ((CHAR_BIT - 1) - bitIdx)) + '0');
      }
   }

   return 0;
}
位字段在字和字节级别工作,不能跨越字边界。C99保证位字段将被尽可能紧密地打包,前提是它们不会跨越存储单元边界(6.7.2.1#10)

一个实现可以分配任何足够大的可寻址存储单元来容纳一个位- 领域如果剩余的空间足够大,则表示一个位字段,该位字段紧跟在另一个位字段之后 结构应封装在同一单元的相邻位中。如果空间不足, 是否将不适合的位字段放入下一个单元或与相邻单元重叠是不确定的 实现定义。单元内位字段的分配顺序(从高阶到低阶) 低阶或低阶到高阶)是实现定义的。路线 未指定可寻址存储单元

如果要将一个单元中的现有位字段填充到下一个单元中,可以使用标准(6.7.2.1#11)中所述的长度为零的位字段:

作为特例,一个宽度为0的位字段结构成员 表示不需要将更多的位字段打包到包含前一位的单元中- 已放置字段(如果有)

此外,它在(6.7.2.1#15)中还提到了一些关于结尾的内容:

结构或联合的末尾可能有未命名的填充


这对您的结构意味着什么:

sizeof(my_struct)     = 8
sizeof(my_struct_var) = 8
Byte 0:  1 0 0 0 0 0 0 1 
Byte 1:  0 0 0 0 0 0 0 1 
Byte 2:  0 0 0 0 0 0 0 0 
Byte 3:  1 0 0 0 0 0 0 0 
Byte 4:  0 0 0 0 1 1 1 0 
Byte 5:  0 0 0 0 0 0 0 0 
Byte 6:  0 0 0 0 0 0 0 0 
Byte 7:  0 0 0 0 0 0 0 0 
#include <stdio.h>
#include <limits.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

typedef enum { ONE, TWO, THREE } my_enum;

typedef struct
{
   unsigned long var1 : 8;
   unsigned long var2 : 24;
   my_enum       var3 : 2;
   my_enum       var4 : 2;
} my_struct;

int main(void)
{
   int idx;
   int bitIdx;
   my_struct my_struct_var;

   memset (&my_struct_var,
           0,
           sizeof(my_struct_var));

   printf("sizeof(my_struct)     = %lu\n", sizeof(my_struct));
   printf("sizeof(my_struct_var) = %lu\n", sizeof(my_struct_var));

   my_struct_var.var1 = 0x81;     /* 1000 0001                     */
   my_struct_var.var2 = 0x800001; /* 1000 0000 0000 0000 0000 0001 */
   my_struct_var.var3 = 0b10;     /* 10                            */
   my_struct_var.var4 = 0b11;     /* 11                            */

   for (idx = 0; idx < sizeof(my_struct_var); ++idx)
   {
      char * curByte = &my_struct_var;
      curByte += idx;
      printf("\nByte %d:  ", idx);
      for (bitIdx = 0; bitIdx < CHAR_BIT; ++bitIdx)
      {
         printf("%c ", ((*curByte & (1 << ((CHAR_BIT - 1) - bitIdx))) >> ((CHAR_BIT - 1) - bitIdx)) + '0');
      }
   }

   return 0;
}
您的
var1
var2
将一起存储在4字节(32位)的内存中,没有任何间隙。由于位字段可以在字节级别运行,因此
var3
var4
也可以存储在一起,表示一个字节。但它们的顺序是实现定义的。 如果在它们之间放置一个零长度的位字段,
var4
将从下一个对齐的单元开始。结构的结尾可以填充到32位或64位


结构的真实代码示例:

sizeof(my_struct)     = 8
sizeof(my_struct_var) = 8
Byte 0:  1 0 0 0 0 0 0 1 
Byte 1:  0 0 0 0 0 0 0 1 
Byte 2:  0 0 0 0 0 0 0 0 
Byte 3:  1 0 0 0 0 0 0 0 
Byte 4:  0 0 0 0 1 1 1 0 
Byte 5:  0 0 0 0 0 0 0 0 
Byte 6:  0 0 0 0 0 0 0 0 
Byte 7:  0 0 0 0 0 0 0 0 
#include <stdio.h>
#include <limits.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

typedef enum { ONE, TWO, THREE } my_enum;

typedef struct
{
   unsigned long var1 : 8;
   unsigned long var2 : 24;
   my_enum       var3 : 2;
   my_enum       var4 : 2;
} my_struct;

int main(void)
{
   int idx;
   int bitIdx;
   my_struct my_struct_var;

   memset (&my_struct_var,
           0,
           sizeof(my_struct_var));

   printf("sizeof(my_struct)     = %lu\n", sizeof(my_struct));
   printf("sizeof(my_struct_var) = %lu\n", sizeof(my_struct_var));

   my_struct_var.var1 = 0x81;     /* 1000 0001                     */
   my_struct_var.var2 = 0x800001; /* 1000 0000 0000 0000 0000 0001 */
   my_struct_var.var3 = 0b10;     /* 10                            */
   my_struct_var.var4 = 0b11;     /* 11                            */

   for (idx = 0; idx < sizeof(my_struct_var); ++idx)
   {
      char * curByte = &my_struct_var;
      curByte += idx;
      printf("\nByte %d:  ", idx);
      for (bitIdx = 0; bitIdx < CHAR_BIT; ++bitIdx)
      {
         printf("%c ", ((*curByte & (1 << ((CHAR_BIT - 1) - bitIdx))) >> ((CHAR_BIT - 1) - bitIdx)) + '0');
      }
   }

   return 0;
}
因为不能获取位字段的地址,所以分析位字段的行为就不那么容易了,下面是我编写的一段代码,通过一些变通方法对其进行分析

我使用易于识别的位模式在结构内部设置值,并打印出整个结构的每一位(总大小为
sizeof()
)。您可以看到,或下面的。请注意,所使用的系统对每个结构变量使用小尾端格式,因此字节交换与humand可读格式(大尾端格式)不同。此外,
var3
var4
的顺序也不同,因为标准规定它是实现定义的

输出:

sizeof(my_struct)     = 8
sizeof(my_struct_var) = 8
Byte 0:  1 0 0 0 0 0 0 1 
Byte 1:  0 0 0 0 0 0 0 1 
Byte 2:  0 0 0 0 0 0 0 0 
Byte 3:  1 0 0 0 0 0 0 0 
Byte 4:  0 0 0 0 1 1 1 0 
Byte 5:  0 0 0 0 0 0 0 0 
Byte 6:  0 0 0 0 0 0 0 0 
Byte 7:  0 0 0 0 0 0 0 0 
#include <stdio.h>
#include <limits.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

typedef enum { ONE, TWO, THREE } my_enum;

typedef struct
{
   unsigned long var1 : 8;
   unsigned long var2 : 24;
   my_enum       var3 : 2;
   my_enum       var4 : 2;
} my_struct;

int main(void)
{
   int idx;
   int bitIdx;
   my_struct my_struct_var;

   memset (&my_struct_var,
           0,
           sizeof(my_struct_var));

   printf("sizeof(my_struct)     = %lu\n", sizeof(my_struct));
   printf("sizeof(my_struct_var) = %lu\n", sizeof(my_struct_var));

   my_struct_var.var1 = 0x81;     /* 1000 0001                     */
   my_struct_var.var2 = 0x800001; /* 1000 0000 0000 0000 0000 0001 */
   my_struct_var.var3 = 0b10;     /* 10                            */
   my_struct_var.var4 = 0b11;     /* 11                            */

   for (idx = 0; idx < sizeof(my_struct_var); ++idx)
   {
      char * curByte = &my_struct_var;
      curByte += idx;
      printf("\nByte %d:  ", idx);
      for (bitIdx = 0; bitIdx < CHAR_BIT; ++bitIdx)
      {
         printf("%c ", ((*curByte & (1 << ((CHAR_BIT - 1) - bitIdx))) >> ((CHAR_BIT - 1) - bitIdx)) + '0');
      }
   }

   return 0;
}
您的结构有效地使用了字节0到3以及字节4的一半。因为我是在64位机器上编译的,而且也是在ideone上编译的,所以半字节4被填充为字节7。我也建议你读这本书

代码:

sizeof(my_struct)     = 8
sizeof(my_struct_var) = 8
Byte 0:  1 0 0 0 0 0 0 1 
Byte 1:  0 0 0 0 0 0 0 1 
Byte 2:  0 0 0 0 0 0 0 0 
Byte 3:  1 0 0 0 0 0 0 0 
Byte 4:  0 0 0 0 1 1 1 0 
Byte 5:  0 0 0 0 0 0 0 0 
Byte 6:  0 0 0 0 0 0 0 0 
Byte 7:  0 0 0 0 0 0 0 0 
#include <stdio.h>
#include <limits.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

typedef enum { ONE, TWO, THREE } my_enum;

typedef struct
{
   unsigned long var1 : 8;
   unsigned long var2 : 24;
   my_enum       var3 : 2;
   my_enum       var4 : 2;
} my_struct;

int main(void)
{
   int idx;
   int bitIdx;
   my_struct my_struct_var;

   memset (&my_struct_var,
           0,
           sizeof(my_struct_var));

   printf("sizeof(my_struct)     = %lu\n", sizeof(my_struct));
   printf("sizeof(my_struct_var) = %lu\n", sizeof(my_struct_var));

   my_struct_var.var1 = 0x81;     /* 1000 0001                     */
   my_struct_var.var2 = 0x800001; /* 1000 0000 0000 0000 0000 0001 */
   my_struct_var.var3 = 0b10;     /* 10                            */
   my_struct_var.var4 = 0b11;     /* 11                            */

   for (idx = 0; idx < sizeof(my_struct_var); ++idx)
   {
      char * curByte = &my_struct_var;
      curByte += idx;
      printf("\nByte %d:  ", idx);
      for (bitIdx = 0; bitIdx < CHAR_BIT; ++bitIdx)
      {
         printf("%c ", ((*curByte & (1 << ((CHAR_BIT - 1) - bitIdx))) >> ((CHAR_BIT - 1) - bitIdx)) + '0');
      }
   }

   return 0;
}
#包括
#包括
#如果字符位!=8.
#错误“不支持的字符大小”
#恩迪夫
typedef enum{1,2,3}my_enum;
类型定义结构
{
无符号长变量1:8;
无符号长变量2:24;
my_enum var3:2;
my_enum var4:2;
}我的结构;
内部主(空)
{
int-idx;
int-bitIdx;
我的结构我的结构变量;
memset(&my_struct_var),
0,
sizeof(my_struct_var));
printf(“sizeof(my_struct)=%lu\n”,sizeof(my_struct));
printf(“sizeof(my_struct_var)=%lu\n”,sizeof(my_struct_var));
my_struct_var.var1=0x81;/*1000 0001*/
my_struct_var.var2=0x800001;/*1000 0000 0001*/
my_struct_var.var3=0b10;/*10*/
my_struct_var.var4=0b11;/*11*/
对于(idx=0;idx((字符位-1)-bitdx))+“0”);
}
}
返回0;
}

C或C++,只选择一种语言,因为你的问题太多,有两种语言。如果有帮助的话,我用的是G+编译器。很难说,因为我一直在做的大项目是