LINUX.ORG.RU

А почему компилятор не умеет делать такие проверки?

 ,


0

1

«A pointer to one type may be converted to a pointer to another type. The resulting pointer may cause addressing exceptions if the subject pointer does not refer to an object suitably aligned in storage.»

Откуда я знаю, как структура выровнена в памяти? Это забота компилятора, а не программиста.


Компиль всё верно глаголет...

A pointer to one type may be converted to a pointer to another type. The resulting pointer may cause addressing exceptions if the subject pointer does not refer to an object suitably aligned in storage.

Откуда компилю знать что Вы от него хотели? В С99 ясно сказано:

6.3.2.3/7 A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer. When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object.

Moisha_Liberman ★★
()
Ответ на: комментарий от Crocodoom

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

Djanik
() автор топика
Ответ на: комментарий от Djanik

Может и делает, если флаги нужные дать компилятору.

Медленно это, поэтому и не делает пока не попросишь.

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

для проверок компилятором -Wcast-align=strict

ещё санитайзер -fsanitize=undefined это ловит.

fsb4000 ★★★★★
()

Хорошо, спрошу по другому. Получаю из сети пакет(заголовок), размером n байт. Есть структура, в том числе и с битовыми полями, как пребразовать указатель на буфер в указатель на структуру, чтобы было можно обращаться к битовым полям по имени?

Djanik
() автор топика
Ответ на: комментарий от Djanik

Выровнять блок памяти, в который ты получаешь пакет так же как выравнивается структура. Либо руками начитывать отдельно каждое поле.

mashmed135
()
Ответ на: комментарий от Djanik

Сразу и без долгих разговоров...

Сюда. Там можете посмотреть как именно люди решают эти вопросы.

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

Moisha_Liberman ★★
()
Ответ на: комментарий от mashmed135

Вообще-то...

Выровнять блок памяти, в который ты получаешь пакет так же как выравнивается структура. Либо руками начитывать отдельно каждое поле.

Для сетевых протоколов как правило предполагается что работа идёт со структурами с атрибутами __packed__ и aligned(x) до кучи. «х» в aligned это степень двойки.

Т.е., получим что-то типа такого:

typedef struct {
     unsigned short some_symbol;
     char symbol_one;
     int symbol_tho;
     char symbol_four;
}__attribute__((packed, aligned(1))) my_sample_struct_t;

Разницу между размерами структуры с атрибутами и без можно посмотреть sizeof(my_sample_struct_t);. Разница и будет объясняться тем, что структура упакована или нет и каково выравнивание между полями структуры.

По скорости так же возможны различия. Неупакованные структуры в случае их динамического выделения, выделяются как правило быстрее, т.к. нет жестких требований к размеру памяти (чтобы влезала вся структура со всеми данными и чтобы было место под заполнение между полями структуры в один блок). Неупакованные и невыровненные структуры в памяти могут располагаться как угодно. С прогалами между полями структуры или без. В общем, слегка быстрее с ними работать, но иногда проблематичнее в части протоколов.

Moisha_Liberman ★★
()
Последнее исправление: Moisha_Liberman (всего исправлений: 2)
Ответ на: Вообще-то... от Moisha_Liberman

Для сетевых протоколов как правило предполагается что работа идёт со структурами с атрибутами packed и aligned(x)

Это детали. И у ТС явно не тот уровень, чтобы в это вдаваться.

mashmed135
()

Откуда я знаю, как структура выровнена в памяти? Это повод программисту об этом специально озаботиться выдав соответствующие инструкции компилятору. Компилятор не в курсе чего там программист делает.

В случае с сетевыми протоколами и вообще бинарными данными на внешних по отношению к программе носителе хорошо бы озадачиться переносимостью и порядком байт в слове

cobold ★★★★★
()

Потому что это C. Он нужен чтобы ты страдал.

hateyoufeel ★★★★★
()
Ответ на: комментарий от mashmed135

Я поэтому...

ТСу и кинул ссыль на libnet. Там можно подсмотреть как люди делают чтобы не изобретать своих каких-то несусветных велосипедов. Ну и заодно, хоть библиотека и старенькая, я где-то годика с 2004 с нею знаком, её можно в ряде случаев использовать в своих целях. Сэкономив себе намного времени. В принципе, если так посмотреть, то с 2004г. в пакетах TCP/IP нового ничего не придумали, а либа позволяет работать с пакетами на любом уровне модели TCP/IP, исключая физический (само собой). Т.е., «скрафтить» можно любой пакет при необходимости.

Moisha_Liberman ★★
()
Ответ на: Я поэтому... от Moisha_Liberman

В принципе, если так посмотреть, то с 2004г. в пакетах TCP/IP нового ничего не придумали

Кроме того что TCP выкидывают потихоньку :D

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

Да...

Кроме того что TCP выкидывают потихоньку :D

Я что-то типа такого слышал, но чёт всё ни как… Да, про http/3 в курсе. =)))

Moisha_Liberman ★★
()
Ответ на: комментарий от hateyoufeel

Семимильными шагами, стремительнее IPv4.

t184256 ★★★★★
()
Ответ на: комментарий от Djanik

Или получай сразу в буфер, который является данной структурой, или копируй в структуры из чарового буфера. Посмотри про strict aliasing, кастовать между двумя произвольными указателями нельзя в общем случае. memcpy(). Если это на плюсах, то можешь заюзать bit_cast<>().

pavlick ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.