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 ★★★★★ ()

Опять в интернете кто-то неправ.

thesis ★★★★★ ()

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

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

sup9999 ()

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

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

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

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

sizeof(char) is always 1. Always.

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

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

C99

The sizeof operator yields the size (in bytes) of its operand

anonymous ()

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

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

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

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

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

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

Одна из цитат — из cpp, вторая — из c99. Ничего?

x3al ★★★★★ ()
Ответ на: 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

Обычно все считают байтом группу из восьми бит

Правильные сишники так не считают :D

anonymous ()
Ответ на: комментарий от 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 ★★★★★ ()
Ответ на: комментарий от asaw

The C standard requires

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

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

Теперь уже ты смешал язык не только с библиотекой, но и с компилятором.

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

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

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

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

Она не просто стандартная, её стандарт - часть стандарта языка)

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

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

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

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

Ок, std::is_pod относится к языку или библиотеке?

Gvidon ★★★★ ()

Придут к дебилам и удивляются, что там дебилы.

anonymous ()
Ответ на: комментарий от 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 ()
Ответ на: комментарий от i-rinat

gcc вообще много магии делает, вплоть до замены printf на puts. Это ничего не говорит о языке.

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

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

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

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

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

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

вплоть до замены printf на puts

Офигеть! Реально заменяет!

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

ABI, инструкции, бинарные форматы - всё это платформа. А что?

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

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

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

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

В любом из этих представлений sizeof(char) == 1.

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

В любом из этих представлений sizeof(char) == 1.

Это опровержение мной сказанного или дополнение?

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

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

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

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