LINUX.ORG.RU

4.2 на хабре

 ,


0

4

В статье http://habrahabr.ru/post/267239/ автор наезжает на общепринятый в C и C++ трюк с использованием union, утверждая, что стандарт такое использование запрещает:

стандарт считает, что читаться всегда должно только то значение, которое было записано ранее. Запись одного типа с последующим чтением другого — undefined behavior.

Есть кто с учёткой на хабре, напишите ему, что он нехороший человек. Цитата из стандарта:

If a standard-layout union contains two or more standard-layout structs that share a common initial sequence, and if the standard-layout union object currently contains one of these standard-layout structs, it is permitted to inspect the common initial part of any of them. Two standard-layout structs share a common initial sequence if corresponding members have layout-compatible types and either neither member is a bit-field or both are bit-fields with the same width for a sequence of one or more initial members.

Нельзя же так на популярном ресурсе делать, могут читать дети.

★★★★

Посоны, а ткните меня в стандарт, где написано:

Во-первых, стандарт требует, чтобы тип char всегда занимал ровно 1 байт памяти.

Я почему-то думал, что

Objects declared as characters (char) shall be large enough to store any member of the implementation’s basic character set.

mkam
()

Вообще-то в статье говорится о

union {
    uint32_t as_int;
    float as_float;
};
И тут common initial sequence отсутствует, так что вы придираетесь.

Sorcerer ★★★★★
()

Зачем ты сюда это принёс? Отнеси назад на хабропомойку.

Psych218 ★★★★★
()

ктото ее читает хабр и воспринимает его в серьез,в 2015-м то

ВЕЛКАМ ТУ РЕАЛ ВОРЛД

sup9999
()

Ты похоже сам не прочитал то что цитируешь из Стандарта. Чувак там всё грамотно пишет.

anonymous
()
Ответ на: комментарий от mkam

Смотреть в Стандарт теперь не в моде, да.

anonymous
()

Ок, прочитал стандарт внимательнее. Был не прав. Печалька.

Gvidon ★★★★
() автор топика
Ответ на: комментарий от i-rinat

Всё правильно. sizeof же не обязательно размер в байтах возвращает.

тоесть то что микрософтовский компилятор для проекта в UTF8 sizeof(char) вернет 2 либо 4 либо 16 (в то время как без утф будет 1)-по твоему не нормально?

а вот микрософт так не считает

sup9999
()
Ответ на: C99 от anonymous

Ой, ты меня поймал.

Проблема тут в том, что именно понимают под байтом. Обычно все считают байтом группу из восьми бит. А в стандарте написано

addressable unit of data storage large enough to hold any member of the basic character set of the execution environment

Ну то есть это может быть и 8, и 16, и 36 бит.

i-rinat ★★★★★
()
Ответ на: комментарий от x3al

Ничего, в C++ так же:

The sizeof operator yields the number of bytes in the object representation of its operand

anonymous
()
Ответ на: комментарий от sup9999

микрософтовский компилятор для проекта в UTF8 sizeof(char) вернет 2 либо 4 либо 16

Не char, а TCHAR и точно не utf-8.

Gvidon ★★★★
() автор топика
Ответ на: комментарий от i-rinat

В <climits>: CHAR_BIT - number of bits in byte

Ещё, вроде как, байт не может быть меньше 8 бит, но может быть больше (UPD: точно - The C standard requires that the integral data type char must hold at least 256 different values, and is represented by at least eight bits (clause 5.2.4.2.1)).

asaw ★★★★★
()
Последнее исправление: asaw (всего исправлений: 1)
Ответ на: комментарий от anonymous

Правильные сишники

Большинство не видело ничего кроме x86. Я, в общем-то, тоже. На виденных мной ARM'ах и MIPS'ах char'ы тоже были по восемь бит. Знания о том, что они бывают других размеров пригодились только для сообщений на ЛОРе. Польза от них сомнительна.

i-rinat ★★★★★
()

Почему якобы неправы на хабре, а бомбит тебя здесь?

Pavval ★★★★★
()
Последнее исправление: Pavval (всего исправлений: 1)
Ответ на: комментарий от i-rinat

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

anonymous
()
Ответ на: комментарий от i-rinat

Хватит гуглить, скачай уже себе драфт стандарта и воюй на здоровье :)

Зачем сразу «воюй»? Я тут просто пополняю запас ненужных знаний, про которые, тем не менее, иногда любят спрашивать разные дрочеры. Ибо, как ты правильно заметил:

На виденных мной ARM'ах и MIPS'ах char'ы тоже были по восемь бит. Знания о том, что они бывают других размеров пригодились только для сообщений на ЛОРе. Польза от них сомнительна.

asaw ★★★★★
()
Ответ на: комментарий от i-rinat

Или вот ещё пример. В сабже написано:

float invert(float f) { 
    uint32_t raw = 0;
    memcpy(&raw, &f, sizeof(float)); 
    raw ^= (1 << 31); // инвертируем знак
    memcpy(&f, &raw, sizeof(float)); 
    return f; 
}

Что интересно: компилятор обязательно заметит, что копируемые регионы всегда заданы однозначно и с фиксированным размером, а потому сможет заменить вызов к системной функции memcpy() на регистровые операции, если оба значения будут у него «на руках» (а так, скорее всего и будет). Таким образом, никакого оверхеда на использование вызова функции здесь нет.

То есть, компилятор знает семантику memcpy() и это даже влияет на кодогенерацию. А кто-то в соседней ветке мне вчера рассказывал, что стандартная библиотека к языку не относится.

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

стандартная библиотека к языку не относится.

Как же она может не относиться, если она «стандартная»? В этом и отличие стандартной библиотеки от любой другой.

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

её стандарт - часть стандарта языка

Я в курсе, именно поэтому она называется стандартной.

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

Расслабься, в данном случае выяснилось, что дебил — я.

Gvidon ★★★★
() автор топика

Вносим ISO/IEC 14882:2014(E) и читаем полностью

In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time. [ Note: One special guarantee is made in order to simplify the use of unions: If a standard-layout union contains several standard-layout structs that share a common initial sequence (9.2), and if an object of this standard-layout union type contains one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of standard-layout struct members; see 9.2. —end note]

Это все, что написано в параграфе 9.5 про доступ к данным в юнионах. Потому при отсутствии common initial sequence, имеем доступ к объекту в памяти, не содержащей объект этого типа, т.е. каноничный UB.

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

Не знаю что это.

Что считать языком - размытый вопрос. Но вот делать выводы на основании того, что компилятор что-то там оптимизирует - это чушь. Он еще много платформоспецифичных оптимизаций делает, что, платформа - тоже часть языка?

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

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

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

Переход на личности? Понемаю.

Компилятору всё разрешено, что не меняет наблюдаемого поведения. Пусть хоть Qt-шные функции оптимизирует.

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

Это был просто намек. Compilation unit - это никакая не платформа, а язык. Чтобы уметь использовать функцию тебе нужен её прототип. А чтобы сделать вышеупомянутую оптимизацию, тебе нужно знать даже не её реализацию (которая может быть неправильной - содержать ошибки), а её смысл. То есть без знания о том, что эта функция должна делать по спецификации, ты такую оптимизацию делать не имеешь права.

asaw ★★★★★
()
Последнее исправление: asaw (всего исправлений: 1)
Ответ на: комментарий от i-rinat

Забей, я неправильно распарсил дискуссию про размер байта.

Тут ещё интересную вещь вычитал на википедии: POSIX requires char to be exactly 8 bits in size. Но я повременю делать из этого какие-либо выводы.

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