код, который дает разные значения в разных онлайн-компиляторах

#c

Вопрос:

У меня есть код, который дает разные значения для разных онлайн-компиляторов, я новичок в программировании на C, пожалуйста, дайте мне знать, ожидаются ли разные значения, пока мы запускаем следующий код на разных онлайн-компиляторах c:

 #include <stdio.h>
struct hai
{
    char c;
    long l;
    char *p;
};
union bye
{
    char c;
    long l;
    char *p;
};
int main (int argc, char *argv[])
{
    struct hai myhai;
    union bye mybye;
    myhai.c = 1;
    myhai.l = 2L;
    myhai.p = "This is myhai";
    mybye.c = 1;
    mybye.l = 2L;
    mybye.p = "This is mybye";
    printf("myhai: %d %ld %sn", myhai.c, myhai.l, myhai.p);
    printf("mybye: %d %ld %sn", mybye.c, mybye.l, mybye.p);
    return 0;
}
 

Комментарии:

1. Стандарт гласит, что чтение из любого элемента в объединении, отличного от последнего записанного, является неопределенным поведением.

2. Ваши поля объединения перезаписываются указателем на символ, поэтому, конечно, это непереносимо. Целочисленные поля с псевдонимами печатают все, что находится в соответствующей части указателя. Это очень непереносимо.

3. @kaylum в C . в C это не UB

4. Почему вы вообще использовали профсоюз? Вы читали, для чего они хороши?

Ответ №1:

Объединение-это место, где участники используют одну и ту же ячейку памяти. В союзе достаточно места только для самого большого его члена.

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

В вашем случае важна запись at. Он сохраняет адрес строкового литерала в объединении. Когда вы читаете c элемент, вы читаете первый байт этого адреса.

Ответ №2:

В объединении поля накладываются друг на друга. Как именно это не определено:

  • Литтл-эндиан и биг-эндиан играют определенную роль, оба поля могут быть выровнены со смещением 0, но там находятся другие значения байтов. (LE = первый байт с наименьшим значением: 257 = 02 01; BE = первый байт с наибольшим значением: 257= 01 02
  • Структура не обнуляется, поэтому после присвоения символа long будет содержать рубиш, и символ, скорее всего, является наименьшим или наиболее значимым байтом.

Комментарии:

1. Не неопределенный, только определенная реализация, определенный способ

2. @0___________ тонкое различие, поэтому один совет: прочитайте определения реализации,

3. каламбур с объединением-один из безопасных (но определяемых реализацией) способов каламбура типа. Поведение не является неопределенным. В C это не определено. В C не является неопределенным.

4. от стандарта C: if the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called "type punning"). This might be a trap representation.

5. @0___________ и там я подумал, что C всегда был лучше. Спасибо за эту проницательность.