Как я могу заполнить все байты заполнения некомпактной структуры определенным значением? - PullRequest
0 голосов
/ 19 марта 2019

Мы знаем, что по причине выравнивания структура может иметь внутренние байты заполнения.

Как мне заполнить все байты заполнения некомпактной структуры определенным значением? Другими словами, рассмотрим следующий сегмент кода:

struct Foo;

// Is that possible to implement pad_Foo() function? If Yes, How?
void pad_Foo(struct Foo *pFoo_x, char pad_byte);

void bar(struct Foo *pFoo_x, int fd, char pad_byte)
{
    // reading in *pFoo_x from a file.
    // It may get some garbage padding bytes.
    read(fd, pFoo_x, sizeof(struct Foo));

    pad_Foo(&x, pad_byte);
}

Возможно ли реализовать функцию pad_Foo (), и если ответ - да, как?

1 Ответ

1 голос
/ 19 марта 2019

Возможно ли реализовать функцию pad_Foo ()

В качестве стандартного кода соответствия ответ нет

Начиная с проекта C11 n1570, 6.2.6 Представление типов:

6 Когда значение сохраняется в объекте структуры или типа объединения, в том числе в объекте-члене, байты представления объекта, которые соответствуют любых байтов заполнения, принимают неопределенные значения . 51)

и

51) Таким образом, например, при присвоении структуры не нужно копировать какие-либо биты заполнения.

Таким образом, стандарт четко гласит: значением отступа нельзя управлять.

В конкретной системе (платформа, ОС, компилятор) это возможно. Как пример из моей системы:

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

struct s
{
  char c;
  int n;
};

void dump_struct(struct s * p)
{
  unsigned char * u = (unsigned char *)p;
  for (size_t i=0; i < sizeof *p; ++i) printf("%02x ", u[i]);
  printf("\n");
}

int main(){
  printf("sizeof(struct s)=%zu sizeof(char)=%zu sizeof(int)=%zu padding=%zu\n",
         sizeof(struct s), 
         sizeof(char), 
         sizeof(int), 
         sizeof(struct s) - sizeof(char) - sizeof(int));

  struct s sa;
  memset(&sa, 'A', sizeof sa);
  sa.c = '8';
  sa.n = 42;
  dump_struct(&sa);

  struct s sb;
  memset(&sb, 'B', sizeof sa);
  sb.c = '8';
  sb.n = 42;
  dump_struct(&sb);
}

Выход:

sizeof(struct s)=8 sizeof(char)=1 sizeof(int)=4 padding=3
38 41 41 41 2a 00 00 00
38 42 42 42 2a 00 00 00
   ^^^^^^^^
    notice

Так что в моей системе memset записал байты заполнения, но в других системах вы можете увидеть другое поведение.

Добавление такого кода в main:

  unsigned char * u = (unsigned char *)&sb.c;
  u += sizeof sb.c;
  while(u < (unsigned char *)&sb.n)
  {
    *u = 'C';
    ++u;
  }
  dump_struct(&sb);

напечатает дополнительную строку:

38 43 43 43 2a 00 00 00

Итак, еще раз - в моей конкретной системе - было изменено заполнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...