пока это работает, можно я попользуюсь?это значит, что рано или поздно вам попадется компилятор,
Да пользуйтесь сколько хотите, просто когда вроде бы работающий код вдруг сломается и вы сломаете себе голову, ища почему, не удивляйтесь - такие ошибки очень трудно вылавливать.пока это работает, можно я попользуюсь?
это означает, что в новых редакциях языка эти конструкции могут не работать.И что значит нелегально?
Кто же вам это скажет, обновите ардуино ide к примеру, а оно раз и сломалось. Потому как компилятор обновился.А мне вот интересно до какой "поры времени" это будет работать.
Это значит, что по спецификации языка С++ ваш код невалиден. И компилятор, к примеру, может ваш код вообще игнорировать. Например:И что значит нелегально?
void foo( int i )
{
if( i + 100 < i ) std::cout << "overflow\n";
}
В этом, ничего. Но нелегально то, что у вас указатель наА что нелегального в том, что я беру 4 байта из одного места памяти и записываю в другое ?
int32_t
указывает на область памяти, в которой находится float
float
обращаются (ие разименовывают) через указатель на int32_t
Да нет, это нелегально уже в текущих редакциях языка. Это означает, что никто не гарантирует, что поведение программы будет предсказуемым.это означает, что в новых редакциях языка эти конструкции могут не работать.
В этом нет ничего нелегального. Более того существует void*Но нелегально то, что у вас указатель наint32_t
указывает на область памяти, в которой находитсяfloat
Именно.Тут главное понимать что делаешь.
Нет, вы поняли неправильно. Ответ - потому, что язык это запрещает. Вы можете делать, то, что запрещено, но повторюсь, это значит, что никто не гарантирует, что вы можете ожидать пресдказуемого поведения.А в ответ я понял: нельзя потому что может быть "ай-ай-ай как плохо".
Вы будете смеяться, но указатель на байт можно, а вот указатель наНо если взять любой потоковый выод он сводиться к тому, что указатель на байт "бежит" по памяти чужих перемен(ных)..
uint32_t
- нельзя.Стандарт языка С++ и С, раздел "strict aliasing". На русском можно почитать например здесьПодскажите, в каком конкретно описании это преобразование считается некорректным?
СуществованиеВ этом нет ничего нелегального. Более того существует void*
void *
к данной теме никаким боком.Ок, буду иметь в виду, но переписывать код, где использую те же union не буду пока явно ругаться не начнет, в C++17 gcc не ругался компилятор, хотя дефолтный фгаг перепроверю как только так и сразу.Стандарт языка С++ и С, раздел "strict aliasing". На русском можно почитать например здесь https://habr.com/ru/company/otus/blog/443602/
Ещё и char* естьСуществованиеvoid *
к данной теме никаким боком.
Извините, но приведённый Вами раздел не имеет никакого отношения к конвертации типов указателей, которые привёл @Старик Похабыч , от слова "совсем". Почитайте про указатели void *, тогда Вам станет яснее принцип, который он предложил. Да, здесь очень много натяжек, но они связаны по большей части с размерами типов и их выравниваниями, то есть это неплохо бы для универсализации считать непосредственно в коде (sizeof и другие), но сам принцип ничего нелегального в себе не несёт.Стандарт языка С++ и С, раздел "strict aliasing"
СОк, буду иметь в виду, но переписывать код, где использую те же 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 *
к любому указателю, в С++ нельзя.Это не мой код, это код @Старик Похабыч, приведенный на первой странице, про который и идет разговор. Если же вы хотите передатьВаш код совершенно не отражает идеи.
float
как набор байтов, то приведение указателя на float
к указателю на char
или unsigned char
aka byte
делать можно (вернее не приведение указателя, а доступ к памяти по этому указателю), но код то был не об этом.понял о чём идёт речь: автоматическое приведение не действует, но ведь можно явно привести.в С можно приводитьvoid *
к любому указателю, в С++ нельзя.
Нет, не соглашусь, это именно этот случай.И всё же, согласитесь, что это также не те случаи, что описаны по Вашей ссылке.
Вы неправильно поняли и описали симтомы, а не причину. Приведенная проблема лишь одна из тех, которые могут возникнуть. А причина одна - нарушение прямого запрета так делать. Можно, конечно, попрыгать с бубном и попробовать использоватьТам имелось в виду, что при разных опциях оптимизации компилятор может игнорировать параллельную модификацию области памяти, когда известно значение, присвоенное этой области под одним из имён.
volatile
, но как известно, если лечить не проблему, а следствие, то будет только хуже.А и не нужна параллельная модификация. В приведенном коде, что в короткой версии, что в длинной, вполне возможно, что компилятор вообще не сгенерирует код, который читает значениеВ данном случае никакой параллельной модификации нет. Т.е., нет изменения одной области памяти с использованием двух указателей на неё.
f1
как int32_t
и даже volatile
может не помочь. То есть в d1
будет мусор, не зависящий от значения в f1
, и удачи потом такой код отлаживать.То, что написано по ссылке, не первоисточник, а объяснение по русски, поэтому не нужно мне рассказывать, что если по этой ссылке что-то не написано или вы что-то не нашли, то оно не так. Первоисточник - стандарт языка С и С++. Я могу привести вам ссылки на конкретные разделы, то боюсь смысла особого нет.@rGlory, не стоит приводить собственные интерпретации того, что написано про ссылке.
Прямой запрет есть в стандартах языков, в статье описывается, к каким возможным проблемам нарушение этого запрета может приводить."Прямого запрета" тоже нигде нет, есть условия, при которых оптимизатор может работать неверно.
Да в том то и дело, что оптимизатор подходит под все случаи, просто не надо хаками пользоваться и нарушать спеки. Нравится вам неоптимизированный код - ваше право, но не надо рассказывать про опыт или что так делать нужно. Тем более, что в данном случае программу легко исправить так, чтобы работало гарантированно, просто нужно знать, как делать нельзя, а как можно.Но, по опыту, первое, что сделает человек, у которого что-то не работает - выключит этот самый оптимизатор, поскольку алгоритмы его работы не могут подходить под все случаи.
А смысл? Чтобы вам доказать? Да я подозреваю, это бесполезно. А себе мне доказывать не надо, я достаточно хорошо знаю стандарт языка, с которым работаю.Прежде чем говорить, что этот код не работает - попробуйте получить прогнозируемый Вами результат, ведь Вы утверждаете, что он уже сейчас нелегален.
МнеИ чем Вам volatile не подошёл? Тоже, считаете, нелегален?
volatile
подошел всем. Просто это одно из ключевых слов, которое очень часто используется не по делу, именно как бубен, без понимания, что происходит и почему. Что-то не работает, а давайте туда вставим volatile
, вдруг заработает.