为什么我们不能访问我们在结构中填充的位?

时间:2016-05-03 06:37:30

标签: c linux struct padding

我的问题是我们用填充来对齐结构。

typedef struct structb_tag
{
   char c;
   int  i;
} structb_t;

这里我们使用8个字节。为什么我们不能使用那么多的3个字节?

7 个答案:

答案 0 :(得分:3)

  

为什么我们不能使用3个字节

你可以。

为此,请测量实现为struct分配的大小,然后使其成为一个联合,添加一个完全符合测量大小的char数组,然后就可以了。

假设这个

typedef struct structb_tag
{
   char c;
   int i;
} structb_t;

使用八个字节创建,sizeof (structb_t)计算为8,将其更改为以下

typedef union unionb_tag
{
  char bytes[8];
  struct
  {
    char c;
    int i;
  } structb;
}

在可移植性和稳健性方面更可靠的是:

typedef union unionb_tag
{
  struct structb_tag
  {
    char c;
    int i;
  } structb;
  char bytes[sizeof (struct structb_tag)];
}

答案 1 :(得分:1)

如果你正在使用GCC并且空间对你而言是最重要的而不是速度(填充提供)你只能请求编译器不进行填充,struct __attribute__((__packed__)) mystruct,填充是编译器的方式对齐自然界中的结构以便更快地访问。

答案 2 :(得分:0)

你总是可以把结构指针转换成字节指针并访问该结构的任何字节。

这是危险的方法。

答案 3 :(得分:0)

填充是依赖于实现的,它不是由标准定义的,你不能不使用它们,因为没有办法引用填充字节。

答案 4 :(得分:0)

是的,你可以。

container-fluid

答案 5 :(得分:0)

简而言之,我们可以使用这三个字节。

我们需要3个字节填充的原因是用于内存使用优化,因此编译器将帮助我们在c和i之间添加间隙。所以当你使用

typedef struct structb_tag
{
   char        c;
   int         i;
} structb_t;

实际上

typedef struct structb_tag
{
   char        c;
   char[3]     unseen_members;
   int         i;
} structb_t;

访问这些看不见的成员不会导致任何分段错误。从操作系统的角度来看,显式地由程序员声明并由隐式编译器声明的成员之间没有区别。

#include <stdio.h>
#include <string.h>


typedef struct Test {
    char c;
    int i;
} MyTest;

int main() {
    MyTest my_test;
    memset(&my_test, 0, sizeof(my_test)); 

    my_test.c = 1;
    int* int_ptr = (int *)&my_test.c; 

    printf("Size of my_test is %lu\n", sizeof(my_test));
    printf("Value of my_test.c(char) is %d\n", my_test.c);
    printf("Value of my_test.c(int) is %d\n", *int_ptr);
    return 0;
}

这给出了:

Size of my_test is 8
Value of my_test.c(char) is 1
Value of my_test.c(int) is 1

答案 6 :(得分:0)

我们可以使用指向该结构的指针访问结构中的任何字节,并将该指针强制转换为(char *),如果我们相应地增加该指针,那么我们可以访问任何字节,但这不是很好的编程技巧。结构用一些额外的字节填充,这样程序的执行就会变得更快。