LINUX.ORG.RU

Indeterminate value of unsigned char/std::byte

 


0

3

Привет. В плюсах стало можно вычислять значение неинициализированного unsigned char:

int f(bool b)
{
    int x;               // OK: the value of x is indeterminate
    int y = x;           // undefined behavior
    unsigned char c;     // OK: the value of c is indeterminate
    unsigned char d = c; // OK: the value of d is indeterminate
    int e = d;           // undefined behavior
    return b ? d : 0;    // undefined behavior if b is true
}

т.е. этот indeterminate state можно таскать между беззнаковыми чар. Собственно вопросы:

  1. Если правильно понимаю, то unsigned char’у это разрешили потому что у него нет trap representation. Вопрос - почему нельзя это какое-то валидное число присвоить инту? По идее, это не должно отличаться от char c=something; int i=c, т.к. у чар нет trap representation, и любое его битовое представление является валидным.
  2. Где можно применить эту столь ограниченную фичу (таскать между char не прикольно как-то)? Если не ошибаюсь, то все функции/операторы сделают type promotion до int, и привет UB.
★★

Громоногие чебураторы интересуются зачем вообще ходить рядом с UB и неопределёнными значениями? Чебураторы рекомендуют не читать на ночь Чаушес^WАлександреску и прививать себе культуру написания кода.

anonymous
()
  1. Похоже, что британцы придрались к unspecified value в принципе.

  2. Зарегистрировали как issue.

  3. И потом тут (внизу) кто-то это исправил.

Т.е. в итоге они урезали случаи, в которых это indeterminate value не приводит к UB таким образом, чтобы сохранить возможность копирования неинициализированных объектов и развязать компиляторам руки для оптимизаций (о чём британцы и жаловались: это значение неизвестное, но определённое, что накладывает больше ограничений на оптимизатор чем неопределённое значение, за которое можно сразу бить по рукам).

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

C++ не платит за аренду твоей головы

anonymous
()
  1. Невалидное значение - это вполне определенное значение. Поведение - это не значение.

  2. Сам же привел пример return b ? d : 0; // undefined behavior if b is true. Можно построить логику, в которой не залезаем на территорию неопредленного поведения. А clang любит упрощать неопределенное поведение (вполне законно), что иногда просто офигеваешь от такой «самодеятельности».

anonymous
()

Если правильно понимаю, то unsigned char’у это разрешили потому что у него нет trap representation. Вопрос - почему нельзя это какое-то валидное число присвоить инту?

У инта тоже нет trap representation на актуальных архитектурах, любой набор бит из 32 однозначно соответствует корректному инту

Crocodoom ★★★★★
()

В плюсах стало можно вычислять значение неинициализированного unsigned char

Так написано, как будто «стало» только в C++20

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

У инта тоже нет trap representation на актуальных архитектурах

Это забавная тема, правда, в C, а не C++.

В C, по стандарту, indeterminate value определено как unspecified value или trap representation. Чтение unspecified value приводит к uspecified (не undefined!) behavior, чтение trap representation — к undefined behavior. Таким образом, на архитектурах без trap representation чтение indeterminate value не приводит к неопределённому поведению. Однако, разработчикам компиляторов C и UB-санитайзеров похер на стандарт (та же история, что со strict aliasing rule), они считают чтение indeterminate value в C приводящим к неопределённому поведению.

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

И то, и другое — UB. В C++20 — по разным причинам.

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

У инта тоже нет trap representation на актуальных архитектурах, любой набор бит из 32 однозначно соответствует корректному инту

В одной из отписок комитета C под одним defect report-ом сказано, что набор битов не определяет однозначно значения. Важна ещё «история» как появился этот набор битов. Один и тот же набор битов с разной «историей» возникновения может соответствовать разным значениям. indeterminate-значение может быть представлено любым набором битов.

anonymous
()

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

deep-purple ★★★★★
()
Ответ на: комментарий от nikitos

Если процитировать стандарт

9.3  Initializers    [dcl.init]
12. If no initializer is specified for an object, the object is default-initialized.  When storage for an objectwith automatic or dynamic storage duration is obtained, the object has anindeterminate value, and ifno initialization is performed for the object, that object retains an indeterminate value until that valueis replaced (7.6.18). [Note: Objects with static or thread storage duration are zero-initialized, see 6.8.3.2.— end note] If an indeterminate value is produced by an evaluation, the behavior is undefined except in thefollowing cases:
 - можно из чара читать
 - можно в чар записать, опять же - из чара

т.е. любое evaluation из indeterminate, который не unsigned char - UB. Я так и не понял задумки, какой в этом смысл. Имхо, или снять такие жесткие ограничения или deprecated.

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

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

Сделать возможным «побайтовое» копирование даже между объектами, содержащими indeterminate value.

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

Имхо, или снять такие жесткие ограничения или deprecated.

«А в задницу такие имхи.» © Луговский

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

Ну мы можем прочесть из indeterminate char, записать тоже в indeterminate char. Что дальше то? Даже тупое indeterminate char + indeterminate char == UB, так как promotion аргументов до инта.

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

Ну мы можем прочесть из indeterminate char, записать тоже в indeterminate char. Что дальше то?

Всё. Сможешь копировать между «байты» между объектами, содержащими indeterminate value. (Когда доступ к object representation определят как следует).

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

Что-то не доходит. Давай в коде? У нас есть:

struct S {
    int usual_int = 5;
    int indeterminate_int;
}
int main() {
    S s;
    S s_copy{};
}

Как сделать копию s в s_copy без ЮБ?

pavlick ★★
() автор топика
Ответ на: комментарий от pavlick
struct S {
    int usual_int = 5;
    int indeterminate_int;
};
int main() {
    S s;
    S s_copy{};

    unsigned char *ps = reinterpret_cast<unsigned char*>(&s);
    unsigned char *pd = reinterpret_cast<unsigned char*>(&s_copy);
    for (unsigned shift = 0;  shift < sizeof(S);  ++ shift) {
        *pd = *ps;
        ++ pd;
        ++ ps;
    }    
}

Я здесь ничего не наUBнул?

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

Я здесь ничего не наUBнул?

Много всего наUBнул.

anonymous
()

Где можно применить эту столь ограниченную фичу?

Однажды император Николай I, встретившись с Гречем на улице, спросил его:

— Скажите, пожалуйста, Греч: к чему служит в русской азбуке буква «ять»?

— Она служит, Ваше Величество, как знак отличия грамотных от неграмотных, — ответил Греч не задумавшись.

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

Также и C++ нужен чтобы отличать хороших программистов от зубрилок.

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