Строгий псевдоним C ++: разве это не UB из примера MSFT?

На этой странице Что касается определенной структуры Winsock, в примере, похоже, берется адрес структуры и преобразуется полученный указатель в указатель на совершенно другую структуру.

SOCKET ListenSocket;
struct sockaddr_in saServer;
// Bind the listening socket using the information in the sockaddr structure
bind( ListenSocket,(SOCKADDR*) &saServer, sizeof(saServer) );

Вот объявления для двух структур. Это технически неопределенное поведение, верно?

struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
};

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

person ThomasMcLeod    schedule 29.06.2017    source источник
comment
Приведение указателя никогда не нарушает строгого правила псевдонима (кажется, это распространенное заблуждение)   -  person M.M    schedule 29.06.2017
comment
@ M.M, но, конечно, реализация bind должна будет уважать этот указатель, и в этой точке вы нарушаете строгое правило псевдонима, не так ли? (У меня смутное впечатление, что вас может спасти тот факт, что единственный элемент структуры, читаемый через псевдоним, находится в начале структуры и является общим для обеих, но для меня совсем не очевидно, что это верно с точки зрения языкового юриста.)   -  person Harry Johnston    schedule 29.06.2017
comment
Реализации библиотеки @HarryJohnston не подчиняются правилам ISO C ++, они могут даже не быть написаны на C ++   -  person M.M    schedule 29.06.2017
comment
@ M.M, достаточно честно; это решает проблему в данном конкретном контексте. Я предполагаю, что если бы вы реализовывали bind самостоятельно, вы могли бы сделать это безопасным, явно приведя указатель на short , как описано здесь. Я не уверен, что это необходимо, но этого должно быть достаточно.   -  person Harry Johnston    schedule 29.06.2017


Ответы (1)


Между зарождением C (по крайней мере, с 1974 г.) по 1989 г., если две структуры имели общую начальную последовательность, язык однозначно позволял коду использовать указатель одного типа структуры для проверки членов CIS другого. В стандарте C99 это разрешение было ограничено случаями, когда оба типа структуры являются частью типа объединения, полное объявление которого было видно в точке, где проверяется значение CIS; некоторые люди настаивают на том, что, поскольку авторы 1989 г. намеревались наложить такое ограничение, оно применимо и к C89. Кроме того, некоторые разработчики компиляторов настаивают на том, что, поскольку авторы стандарта подразумевали, что эта гарантия применяется только к доступам, сделанным через lvalue типа union, они проигнорируют часть стандарта, в которой говорится, что определение «полного объединения < em> type "должен быть виден.

Реализациям разрешается предоставлять гарантии сверх тех, которые требуются Стандартом. Потому что у людей, не обладающих экстрасенсорными способностями, которые писали код до C99, не было причин ожидать, что им нужно будет включить ненужные в противном случае декларации объединения, чтобы использовать гарантии CIS, и потому что большая часть кода, написанного с той эпохи, полагается на эти гарантии, несмотря на отсутствие таких деклараций, любой, кто хочет написать реализацию, подходящую для использования с таким кодом, должен поддерживать их, независимо от того, требует ли Стандарт такой поддержки. Хотя нет особенно веских причин, по которым обновления файла заголовка не должны включать объявление типа объединения, я не уверен, сколько компиляторов позаботятся о его наличии или отсутствии. Компиляторы, которые я видел, либо поддерживают гарантии CIS даже без видимого полного объявления типа union, либо нарушают гарантии CIS (игнорируя стандарт), даже если декларация присутствует.

person supercat    schedule 29.06.2017