Перейти к содержанию
    

Указатель на невыровненную память

15 минут назад, sasamy сказал:

я специально даю ссылки чтобы не было претензий про вырванный контекст. Стандарт любо соблюдают либо нет независимо от контекста.

Стандарт что-то говорит о расширениях конкретного компилятора? Может, говорит, что они запрещены?

Накопленная кодовая база не укладывается полностью в ANSI Си, некоторые вещи невозможно воплотить средствами Си строго по стандарту.

Для этого и появились расширения в компиляторах. И да, какие-то из них вполне могут "отменить" UB, давая вполне однозначное поведение.

Компиляторы пишут не те же люди, которые пишут стандарт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 1:15 PM, Arlleex said:

 И да, какие-то из них вполне могут "отменить" UB, давая вполне однозначное поведение.

да ничего они не могут отменить - есть архитектуры на которых невыровненный доступ невозможен, а код ваш нестандартный и непереносимый.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 минут назад, sasamy сказал:

да ничего они не могут отменить - есть архитектуры на которых невыровненный доступ невозможен, а код ваш нестандартный и непереносимый.

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

Попробуйте скомпилировать на чисто ANSI Си программу, где нужно манипулировать с упакованными структурами - без расширений компилятора все придется делать вручную. Поэтому в ANSI Си никто не кодит. Строго говоря, почти все ныне существующие компиляторы Си - это компиляторы Си-подобного языка.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 1:57 PM, Arlleex said:

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

а сразу по стандарту написать не вариант ?

 

On 10/22/2023 at 1:57 PM, Arlleex said:

Попробуйте скомпилировать на чисто ANSI Си программу, где нужно манипулировать с упакованными структурами - без расширений компилятора все придется делать вручную.

и в чём проблема сделать вручную - лишний байтик не сэкономится ?

https://godbolt.org/z/Ta9o7Yrnn

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 минут назад, sasamy сказал:

а сразу по стандарту написать не вариант ?

Потому что синтаксически некрасиво. Вместо a = b писать a = load_u16(&b), еще и держа в голове тип a и, возможно, еще и b.

Да и банально дольше - даже с оптимизацией не факт, что вызовы функций встроятся.

И для архитектур, поддерживающих невыровненный доступ, это неэффективный путь.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 2:16 PM, Arlleex said:

Да и банально дольше - даже с оптимизацией не факт, что вызовы функций встроятся.

ассемблерный выхлоп посмотрите и всё ясно станет - в любом случае код будет корректный

On 10/22/2023 at 2:16 PM, Arlleex said:

Вместо a = b писать a = load_u16(&b), еще и держа в голове тип a и, возможно, еще и b.

удивительная избирательность, a = b вы пишете не разбирая их типы ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 минут назад, sasamy сказал:

ассемблерный выхлоп посмотрите и всё ясно станет - в любом случае код будет корректный

Корректный, но неэффективный. Выбирать тут можно долго, кому что. Я буду пользоваться возможностями компилятора, он для этого и сделан, чтобы рутинные операции, в том числе, щелкать.
 

Цитата

удивительная избирательность, a = b вы пишете не разбирая их типы ?

В большинстве случаев нет необходимости знать точную ширину типа. Например

struct Frame {
  u8 cnt;
  u8 data[256];
};

void parseFrame(struct Frame *f) {
  u32 const cnt = f->cnt; // или для C++ auto const cnt = f->cnt;
  u32 const cmd = f->data[0];
  
  switch (cmd) {
    ...
  }
}


Зачем мне помнить точную ширину или тип переменной, которую читаю? Знаковость еще может понадобиться, но ширина - чаще всего, для рядового использования - нет. Поэтому оставляю сие за компилятором - пусть сам решает, как ему лучше читать. Может, решит что-нибудь оптимизировать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 2:47 PM, Arlleex said:

Зачем мне помнить точную ширину или тип переменной, которую читаю?

чтобы результат вычислений правильный был ? там ведь может float по протоколу быть

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 минуту назад, sasamy сказал:

чтобы результат вычислений правильный был ? там ведь может float по протоколу быть

Программирование, в первую очередь - умение правильно давать имена сущностям. Обычно из контекста сразу понятно, какие типы используются. При возникновении неоднозначностей можно и подсмотреть. Лично мне весьма редко приходится натыкаться на такие случаи, а тем более, когда контекст требует целый тип, а "по протоколу" - почему-то float.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

22 часа назад, Arlleex сказал:

Ну и тогда уж, если не сложно, прошу Вас привести листинг следующего теста в IAR

#pragma pack(push, 1)
struct PackStr {
  u64 d64;
};
#pragma pack(pop)

volatile struct {
  u8      d8;
  PackStr p64;
}UnalignStr;

int main() {
  UnalignStr.p64.d64; // <- какая инструкция CPU для Cortex-M4 будет применена?
}

Никакая естественно не будет применена. Пример некорректный.

Нужно чтобы была операция:

#pragma pack(push, 1)                                                                   
struct PackStr {                                                                        
  u64 d64;                                                                              
};                                                                                      
#pragma pack(pop)                                                                       
                                                                                        
volatile struct {                                                                       
  u8      d8;                                                                           
  PackStr p64;                                                                          
                                                                                        
                    In section .bss, align 4                                            
} UnalignStr;                                                                           
        UnalignStr:                                                                     
                    DS8 12                                                              
                                                                                        
                                                                                        
                    In section .text, align 2, keep-with-next                           
int main1() {                                                                           
  u64 q = UnalignStr.p64.d64; // <- какая инструкция CPU для Cortex-M4 будет применена? 
        _Z5main1v: (+1)                                                                 
 0x....             LDR.N    R0,??DataTable26_53                                        
 0xF8D0 0x2001      LDR      R2,[R0, #+1]                                               
 0xF8D0 0x3005      LDR      R3,[R0, #+5]                                               
  return 1;                                                                             
 0x2001             MOVS     R0,#+1                                                     
 0x4770             BX       LR               ;; return                                 
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, sasamy сказал:

да ничего они не могут отменить - есть архитектуры на которых невыровненный доступ невозможен, а код ваш нестандартный и непереносимый.

Есть архитектуры где char 16-битный а еще есть мэйнфреймы. И чего российским эммбеддерам задумываться о недоступных сущностях ? Написать Универсальный Решатель Всех Задач для любого CPU жизни не хватит.
Общеупотребительны AVR, Cortex-M0, M3, M4. Невыровненный доступ из перечисленных не умеет только M0. Его волевым решением отправляем фтопку и проблема невыровненного доступа перестает существовать.
Заказчику нужно решение его прикладной задачи а за соблюдение сферического стандарта в вакууме он не платит. А сделать как всегда надо "вчера".
Мегажадные заказчики которым вынь да положь код под M0 или иной брейнфак должны оплатить глубокую переработку кода по полной программе.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 10/22/2023 at 5:53 PM, _3m said:

И чего российским эммбеддерам задумываться о недоступных сущностях ?

Общеупотребительны AVR, Cortex-M0, M3, M4. Невыровненный доступ из перечисленных не умеет только M0.

вы уверены что они останутся доступны ? Что касается riscv

https://inst.eecs.berkeley.edu/~cs61c/sp20/pdfs/lectures/lec06.pdf

Quote

RISC-V does not require that integers be word aligned...
• But it is very very bad if you don't make sure they are...
• Consequences of unaligned integers
• Slowdown: The processor is allowed to be a lot slower when it happens
In fact, a RISC-V processor may natively only support aligned accesses, and do
unaligned-access in software!

An unaligned load could take hundreds of times longer!
• Lack of atomicity: The whole thing doesn't happen at once...
can introduce lots of very subtle bugs
• So in practice, RISC-V requires integers to be aligned on 4-
byte boundaries

Изменено пользователем sasamy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, jcxz сказал:

Никакая естественно не будет применена. Пример некорректный.

Нужно чтобы была операция:

Почему некорректный? Чтобы volatile был считан, достаточно, в общем-то, написать так, как я написал. За листинг благодарю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, Arlleex сказал:

Почему некорректный? Чтобы volatile был считан, достаточно, в общем-то, написать так, как я написал.

Так как вы написали - никакого кода не создаётся. Только варнинг генерится. Проверьте сами, если не верите.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 минут назад, jcxz сказал:

Так как вы написали - никакого кода не создаётся. Только варнинг генерится. Проверьте сами, если не верите.

Дык в том и дело, что проверял. Генерирует чтение. Ради интереса, даже GCC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...