Как отключить отладку структуры в C без использования pragma?
Отключить отладку структуры в C без использования прагмы
Ответ 1
Нет стандартного способа сделать это. В стандарте указано, что отступы могут выполняться по усмотрению реализации. Из C99 6.7.2.1 Structure and union specifiers
, пункт 12:
Каждый член, не являющийся битовым полем структуры или объекта объединения, выравнивается в соответствии с реализацией, соответствующей его типу.
Сказав это, вы можете попробовать несколько вещей.
Сначала вы уже уклонились, используя #pragma
, чтобы попытаться убедить компилятор не упаковывать. В любом случае, это не переносимо. Также нет других способов реализации, но вы должны проверить их, поскольку это может потребоваться для этого, если вам действительно нужна эта возможность.
Во-вторых, вы должны упорядочить свои поля в порядке наибольшего размера, такие как все типы long long
, за которыми следуют теги long
, а затем все типы int
, short
и, наконец, char
. Обычно это работает, поскольку чаще всего это более крупные типы, которые имеют более строгие требования к выравниванию. Опять же, не переносимый.
В-третьих, вы можете определить свои типы в качестве char
массивов и отбросить адреса, чтобы не было отступов. Но имейте в виду, что некоторые архитектуры будут замедляться, если переменные не будут правильно выровнены, а другие будут терпеть неудачу (например, повышение ошибки шины и завершение вашего процесса, например).
Это последнее имеет некоторые дополнительные объяснения. Скажем, у вас есть структура с полями в следующем порядке:
char C; // one byte
int I; // two bytes
long L; // four bytes
С дополнением вы можете получить следующие байты:
CxxxIIxxLLLL
где x
- это отступы.
Однако, если вы определяете свою структуру как:
typedef struct { char c[7]; } myType;
myType n;
вы получаете:
CCCCCCC
Затем вы можете сделать что-то вроде:
int *pInt = &(n.c[1]);
int *pLng = &(n.c[3]);
int myInt = *pInt;
int myLong = *pLng;
чтобы дать вам:
CIILLLL
Опять же, к сожалению, не переносится.
Все эти "решения" полагаются на то, что вы знакомы со своим компилятором и базовыми типами данных.
Ответ 2
Помимо параметров компилятора, таких как pragma pack, вы не можете, заполнение находится в стандарте C.
Вы всегда можете попытаться уменьшить заполнение, объявив наименьшие типы, последние в структуре, как в:
struct _foo {
int a; /* No padding between a & b */
short b;
} foo;
struct _bar {
short b; /* 2 bytes of padding between a & b */
int a;
} bar;
Примечание для реализаций с 4 байтовыми границами
Ответ 3
На некоторых архитектурах процессор сам будет подвергать объекту, если его попросят работать с несогласованными данными. Чтобы обойти это, компилятор мог генерировать несколько выровненных инструкций чтения или записи, сдвигать и разделять или объединять различные биты. Вы можете разумно ожидать, что он будет в 5 или 10 раз медленнее, чем согласованная обработка данных. Но стандарт не требует, чтобы компиляторы были готовы сделать это... учитывая стоимость исполнения, это просто не востребовано. Компиляторы, которые поддерживают явный контроль над заполнением, предоставляют свои собственные прагмы именно потому, что прагмы зарезервированы для нестандартных функций.
Если вы должны работать с незакрепленными данными, подумайте о том, чтобы написать свои собственные процедуры доступа. Возможно, вам захочется поэкспериментировать с типами, для которых требуется меньшее выравнивание (например, использование char/int8_t), но все же возможно, что, например, размер структур будет округлен до кратных 4, что затруднит структуру упаковки, и в этом случае вам понадобится реализовать свой собственный доступ для всей области памяти.
Ответ 4
Либо вы позволяете компилятору дополнять, либо говорить, что это не нужно делать с помощью #pragma, либо вы просто используете несколько пучков байтов, как массив char, и сами создаете все свои данные (перемещая и добавляя байты). Это действительно неэффективно, но вы точно контролируете расположение байтов. Я делал это, иногда готовая сетевые пакеты вручную, но в большинстве случаев это плохая идея, даже если она стандартная.
Ответ 5
Если вам действительно нужны структуры без заполнения: Определите типы данных замены для short, int, long и т.д., используя структуры или классы, состоящие только из 8-битных байтов. Затем составьте свои структуры более высокого уровня, используя заменяющие типы данных.
Перегрузка оператора С++ очень удобна, но вы можете добиться такого же эффекта в C, используя структуры вместо классов. В приведенных ниже реализациях внедрения и присваивания предполагается, что ЦП может обрабатывать смещенные 32-битные целые числа, но в других реализациях могут использоваться более строгие ЦП.
Вот пример кода:
#include <stdint.h>
#include <stdio.h>
class packable_int { public:
int8_t b[4];
operator int32_t () const { return *(int32_t*) b; }
void operator = ( int32_t n ) { *(int32_t*) b = n; }
};
struct SA {
int8_t c;
int32_t n;
} sa;
struct SB {
int8_t c;
packable_int n;
} sb;
int main () {
printf ( "sizeof sa %d\n", sizeof sa ); // sizeof sa 8
printf ( "sizeof sb %d\n", sizeof sb ); // sizeof sb 5
return 0;
}
Ответ 6
Мы можем отключить отладку структуры в программе c любым из следующих способов.
- > используйте __attribute__((packed))
за определением структуры. например,
struct node {
char x;
short y;
int z;
} __attribute__((packed));
- > использовать флаг -fpack-struct
при компиляции c-кода. например,
$ gcc -fpack-struct -o tmp tmp.c
Надеюсь, это поможет. Спасибо.