Передача float

bort707

★★★★★★✩
21 Сен 2020
3,066
914
это значит, что рано или поздно вам попадется компилятор,
пока это работает, можно я попользуюсь? :)
У Похабыча, конечно, жуть накручена - но общий принцип преобразования через кастинг применяется в С много лет
 

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
пока это работает, можно я попользуюсь?
Да пользуйтесь сколько хотите, просто когда вроде бы работающий код вдруг сломается и вы сломаете себе голову, ища почему, не удивляйтесь - такие ошибки очень трудно вылавливать.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
@rGlory, А мне вот интересно до какой "поры времени" это будет работать. И что значит нелегально? С++ позволяет делать много нелегального. А что нелегального в том, что я беру 4 байта из одного места памяти и записываю в другое ? В ассемблере вроде как даже есть такая команда.
Другое дело, что можно по своему неведению наткнуться на это о го го как, то это другой дело.

Жуть накрутил для понимания , и разжевывания. Пошагово!
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
О! А этот ответ меня устроил! (с)
Это как с библиотеками, используешь их используешь, а потом бац, новая версия и все что ты там наиспользовал оказывается нелегально...
 

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
А мне вот интересно до какой "поры времени" это будет работать.
Кто же вам это скажет, обновите ардуино ide к примеру, а оно раз и сломалось. Потому как компилятор обновился.
И что значит нелегально?
Это значит, что по спецификации языка С++ ваш код невалиден. И компилятор, к примеру, может ваш код вообще игнорировать. Например:
Код:
void foo( int i )
{
   if( i + 100 < i ) std::cout << "overflow\n";
}
Казалось бы что тут такого, такой хитрый хак, С++ позволяет делать такое. Но уже есть компиляторы, которые такую проверку просто выбрасывают. Легко будет поймать?

А что нелегального в том, что я беру 4 байта из одного места памяти и записываю в другое ?
В этом, ничего. Но нелегально то, что у вас указатель на int32_t указывает на область памяти, в которой находится float

Уточню, я слишком упростил. Нелегально, что к области памяти, в которой находится float обращаются (ие разименовывают) через указатель на int32_t

это означает, что в новых редакциях языка эти конструкции могут не работать.
Да нет, это нелегально уже в текущих редакциях языка. Это означает, что никто не гарантирует, что поведение программы будет предсказуемым.
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Тут главное понимать что делаешь. Да, напрямую нельзя взаимодействовать с указателями разных типов. Но тут же есть вариант как это можно сделать.
А в ответ я понял: нельзя потому что может быть "ай-ай-ай как плохо". Но если взять любой потоковый выод он сводиться к тому, что указатель на байт "бежит" по памяти чужих перемен(ных)..
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
@rGlory, извините, но, похоже, это Вы не правы. Подскажите, в каком конкретно описании это преобразование считается некорректным? Преобразования типов были, есть и будут в языке всегда. Ну, например, зачем тогда использовать указатель void *?
 
  • Лойс +1
Реакции: kDn

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
Тут главное понимать что делаешь.
Именно.
А в ответ я понял: нельзя потому что может быть "ай-ай-ай как плохо".
Нет, вы поняли неправильно. Ответ - потому, что язык это запрещает. Вы можете делать, то, что запрещено, но повторюсь, это значит, что никто не гарантирует, что вы можете ожидать пресдказуемого поведения.
Но если взять любой потоковый выод он сводиться к тому, что указатель на байт "бежит" по памяти чужих перемен(ных)..
Вы будете смеяться, но указатель на байт можно, а вот указатель на uint32_t - нельзя.
Подскажите, в каком конкретно описании это преобразование считается некорректным?
Стандарт языка С++ и С, раздел "strict aliasing". На русском можно почитать например здесь
https://habr.com/ru/company/otus/blog/443602/

В этом нет ничего нелегального. Более того существует void*
Существование void * к данной теме никаким боком.
 
Изменено:
  • Лойс +1
Реакции: kDn

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
Стандарт языка С++ и С, раздел "strict aliasing". На русском можно почитать например здесь https://habr.com/ru/company/otus/blog/443602/
Ок, буду иметь в виду, но переписывать код, где использую те же union не буду пока явно ругаться не начнет, в C++17 gcc не ругался компилятор, хотя дефолтный фгаг перепроверю как только так и сразу.

Существование void * к данной теме никаким боком.
Ещё и char* есть :)
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
Стандарт языка С++ и С, раздел "strict aliasing"
Извините, но приведённый Вами раздел не имеет никакого отношения к конвертации типов указателей, которые привёл @Старик Похабыч , от слова "совсем". Почитайте про указатели void *, тогда Вам станет яснее принцип, который он предложил. Да, здесь очень много натяжек, но они связаны по большей части с размерами типов и их выравниваниями, то есть это неплохо бы для универсализации считать непосредственно в коде (sizeof и другие), но сам принцип ничего нелегального в себе не несёт.
 

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
Ок, буду иметь в виду, но переписывать код, где использую те же union не буду пока явно ругаться не начнет, в C++17 gcc не ругался компилятор, хотя дефолтный фгаг перепроверю как только так и сразу.
С union ситуация неопределенная - для С это валидный код, а для С++ невалидный. Ситуация, что компилятор именно в режиме С++ начнет выдавать невалидный код, маловероятна, хотя возможна.

Извините, но приведённый Вами раздел не имеет никакого отношения к конвертации типов указателей, которые привёл @Старик Похабыч , от слова "совсем".
Ну да, конечно:
Код:
  float f1 = 123.456;
  Serial.println(f1);

  void * u1;
  u1=&f1; 
  uint32_t * ud;
  ud=u1;
  uint32_t d1;
  d1 = *ud;
Который можно упростить до
Код:
    float f1 = 123.456;
    uint32_t d1 = *reinterpret_cast<uint32_t *>( &f1 );
Не имеет никакого отношения, вы уверены?

Кстати оригинальный код в С++ компилироваться не будет, в С можно приводить void * к любому указателю, в С++ нельзя.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942

@rGlory, Ваш код совершенно не отражает идеи. При передаче данные никак не преобразуются и не интерпретируются, в Вашем коде Вы присваиваете область памяти, содержащую float, переменной, имеющей ту же длину, но имеющую тип uint32_t. Так и не поняли принципа.
По поводу void - проверю, не уверен, что это так.
 

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
Ваш код совершенно не отражает идеи.
Это не мой код, это код @Старик Похабыч, приведенный на первой странице, про который и идет разговор. Если же вы хотите передать float как набор байтов, то приведение указателя на float к указателю на char или unsigned char aka byte делать можно (вернее не приведение указателя, а доступ к памяти по этому указателю), но код то был не об этом.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
Код @Старик Похабыч я не смотрел, прочитал только описание. Преобразование типов через переменные выглядит ужасно, здесь соглашусь, но @Старик Похабыч пояснил, что сделал это во многом в учебных целях. И всё же, согласитесь, что это также не те случаи, что описаны по Вашей ссылке. Там имелось в виду, что при разных опциях оптимизации компилятор может игнорировать параллельную модификацию области памяти, когда известно значение, присвоенное этой области под одним из имён. В данном случае никакой параллельной модификации нет. Т.е., нет изменения одной области памяти с использованием двух указателей на неё.
Кстати, есть же модификатор volatile, который говорит оптимизатору, что переменная может измениться в любой момент другим процессом.

в С можно приводить void * к любому указателю, в С++ нельзя.
понял о чём идёт речь: автоматическое приведение не действует, но ведь можно явно привести.
 
Изменено:

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
И всё же, согласитесь, что это также не те случаи, что описаны по Вашей ссылке.
Нет, не соглашусь, это именно этот случай.
Там имелось в виду, что при разных опциях оптимизации компилятор может игнорировать параллельную модификацию области памяти, когда известно значение, присвоенное этой области под одним из имён.
Вы неправильно поняли и описали симтомы, а не причину. Приведенная проблема лишь одна из тех, которые могут возникнуть. А причина одна - нарушение прямого запрета так делать. Можно, конечно, попрыгать с бубном и попробовать использовать volatile, но как известно, если лечить не проблему, а следствие, то будет только хуже.
В данном случае никакой параллельной модификации нет. Т.е., нет изменения одной области памяти с использованием двух указателей на неё.
А и не нужна параллельная модификация. В приведенном коде, что в короткой версии, что в длинной, вполне возможно, что компилятор вообще не сгенерирует код, который читает значение f1 как int32_t и даже volatile может не помочь. То есть в d1 будет мусор, не зависящий от значения в f1, и удачи потом такой код отлаживать.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942

@rGlory, не стоит приводить собственные интерпретации того, что написано про ссылке. Там приведено много случаев и ни один из них не подходит под приведённый код. "Прямого запрета" тоже нигде нет, есть условия, при которых оптимизатор может работать неверно. Но, по опыту, первое, что сделает человек, у которого что-то не работает - выключит этот самый оптимизатор, поскольку алгоритмы его работы не могут подходить под все случаи.
Прежде чем говорить, что этот код не работает - попробуйте получить прогнозируемый Вами результат, ведь Вы утверждаете, что он уже сейчас нелегален.
И чем Вам volatile не подошёл? Тоже, считаете, нелегален?
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
@poty, риск UB достаточно веский аргумент в пользу правоты @rGlory. Для меня неопределенное поведение равнозначно запрету, поэтому код МОЖЕТ выполняться верно, но делать на это ставку мягко говоря не правильно. Поэтому лично я благодарен за предупреждение о реальном положении дел... Это не значит, что прям щаз брошусь переписывать весь проверенный код, но по крайней мере буду знать откуда грабли ждать.

Вы похоже пошли на принцип в этом вопросе, но всеж-таки правота на стороне rGlory ИМХО.
 

rGlory

★✩✩✩✩✩✩
11 Май 2021
200
20
@rGlory, не стоит приводить собственные интерпретации того, что написано про ссылке.
То, что написано по ссылке, не первоисточник, а объяснение по русски, поэтому не нужно мне рассказывать, что если по этой ссылке что-то не написано или вы что-то не нашли, то оно не так. Первоисточник - стандарт языка С и С++. Я могу привести вам ссылки на конкретные разделы, то боюсь смысла особого нет.
"Прямого запрета" тоже нигде нет, есть условия, при которых оптимизатор может работать неверно.
Прямой запрет есть в стандартах языков, в статье описывается, к каким возможным проблемам нарушение этого запрета может приводить.
Но, по опыту, первое, что сделает человек, у которого что-то не работает - выключит этот самый оптимизатор, поскольку алгоритмы его работы не могут подходить под все случаи.
Да в том то и дело, что оптимизатор подходит под все случаи, просто не надо хаками пользоваться и нарушать спеки. Нравится вам неоптимизированный код - ваше право, но не надо рассказывать про опыт или что так делать нужно. Тем более, что в данном случае программу легко исправить так, чтобы работало гарантированно, просто нужно знать, как делать нельзя, а как можно.
Прежде чем говорить, что этот код не работает - попробуйте получить прогнозируемый Вами результат, ведь Вы утверждаете, что он уже сейчас нелегален.
А смысл? Чтобы вам доказать? Да я подозреваю, это бесполезно. А себе мне доказывать не надо, я достаточно хорошо знаю стандарт языка, с которым работаю.

И чем Вам volatile не подошёл? Тоже, считаете, нелегален?
Мне volatile подошел всем. Просто это одно из ключевых слов, которое очень часто используется не по делу, именно как бубен, без понимания, что происходит и почему. Что-то не работает, а давайте туда вставим volatile, вдруг заработает.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
Давайте вспомним, что язык в arduino IDE отличается от канонического С++, поэтому строгие требования С++ к нему можно применять а можно и нет.
Если использовать более строгую среду или более строгую компиляцию могут посыпаться ошибки и предупреждения. А можно использовать "запрещенные" конструкции , которые будут 200 лет работать в конкретном случае без перезапуска.
Не будем забывать фразу "незнание закона не освобождает от ответственности, за то знание очень часто".
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,266
1,303
Москва
к иде штатно прикручен компилятор С++, написаны максросы и выставлены флаги компиляции.

И что интересно программисты сишники в зависимости от текущего настроения все эти "хаки" и "трюки" могут заносить языку то в + то в - :D