Що станеться, якщо невизначена поведінка C ++ відповідає поведінці, визначеній C?


10

У мене є *.cppфайл, який я компілюю за допомогою C ++ (не компілятор C). Функція, що містить, покладається на заголовок (див. Останній рядок), який, здається, визначений в C (будь ласка, виправте, якщо я помиляюся!), Але не в C ++ для цього спеціального типу.

[...] C++ code [...]

struct sockaddr_in sa = {0};
int sockfd = ...;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(sockfd, (struct sockaddr *)&sa, sizeof sa);

[...] C++ code [...]

Оскільки я компілюю це у файлі C ++, це тепер визначене чи невизначене поведінка? Або мені потрібно перенести це у *.cфайл, щоб визначити його поведінку?


1
Розширення файлу не має значення; лише якщо ви компілюєте це як C або C ++.
Фредрік

1
Відповідні типи не успадковуються один від одного і не мають жодних стосунків, і це не визначено в C ++
Daniel Stephens

1
Як правило, якщо файл має .cрозширення, компілятор C викликається автоматично.
Ігор Р.

1
Я цей трюк роблю весь час у коді C ++. Поняття не маю, чому це не працює для вас. Десь пропущений заголовок?
користувач4581301

3
@DanielStephens Ця програма ніколи не намагається знизити покажчик. Самі касти дозволені , перенаправлення - лише іноді. Якщо сторона C правильно відкидає покажчик назад до реального типу, то все повинно бути добре. Проблеми з литтям можуть виникнути, якби ці типи мали різні вимоги до вирівнювання.
користувач7860670

Відповіді:


6

Це визначено як для C ++, так і для C. Це не порушує суворих правил дозволу, оскільки не знищує отриманий вказівник.

Ось цитата з C ++ (завдяки @interjay та @VTT), яка дозволяє це:

Об'єктний вказівник може бути явно перетворений у вказівник об'єкта іншого типу.

Ось цитата з C (спасибі @StoryTeller), яка дозволяє це:

Вказівник на тип об'єкта може бути перетворений у вказівник на інший тип об'єкта.

Вони вказують, що один тип вказівника може бути перетворений в інший тип вказівника (а потім необов'язково перетворений назад) без наслідків.

Ось цитата з POSIX, яка дозволяє цей конкретний випадок:

Структура sockaddr_in використовується для зберігання адрес для сімейства адрес Інтернет. Покажчики на цей тип подаються додатками для структури sockaddr * для використання з функціями socket.

Оскільки ця функція ( bind) є частиною стандартної бібліотеки С, все, що відбувається всередині (зокрема, перенаправлення покажчика з типовим типом), не має визначеного поведінки.


Щоб відповісти на більш загальне запитання:

C і C ++ - це дві різні мови. Якщо щось визначено в C, але не в C ++, це визначено в C, але не в C ++. Жодна неявна сумісність між двома мовами це не змінить. Якщо ви хочете використовувати код, чітко визначений у C, але не визначений у C ++, вам доведеться використовувати компілятор C для компіляції цього коду.


1
@interjay Чи можете ви підкріпити це цитатою зі стандарту (або C, або C ++ - це добре)?
СС Енн


1
@StoryTeller Дякую Натомість додана версія HTTP.
СС Енн

2
Можливо, це дефект стандарту POSIX - другий аргумент bindповинен бути a const void *, але bindпередує існуванню voidмови C (і взагалі існування C ++). Вони оновили його в якийсь момент, щоб додати constосновний тип, але ніколи не виправляли.
Кріс Додд

1
Я можу порекомендувати цю розмову youtube.com/watch?v=_qzMpk-22cc Я все ще не впевнений, чи підтверджує вона відповідь, чи це насправді говорить протилежне: -o C ++ - це кошмар .. lol
Даніель Стівенс

-3

Дзвінки між кодом C і C ++ усі викликають не визначене поведінку з точки зору відповідних стандартів, але більшість платформ визначають такі речі.

У ситуаціях, коли частини стандарту C або C ++ та документація на впровадження разом визначають або описують дію, але інші частини характеризують її як Не визначено, реалізаціям дозволяється обробляти код будь-яким способом, який найкращим чином задовольнятиме потреби своїх клієнтів або - якщо вони байдужі до потреб клієнтів - незалежно від моди, яку вони вважають за потрібне. Той факт, що Стандарт розглядає такі питання як поза їх юрисдикцією, не передбачає жодного судження про те, коли та / або як реалізація, яка вимагає придатності для різних цілей, повинна очікувати їх серйозної обробки, але деякі виконавці компіляторів підписуються міфом, який він робить.


Перший абзац: "Дзвінки між кодом C та C ++ усі викликають не визначене поведінку" Навіть якщо існувало таке поняття, як "виклик невизначеної поведінки" (чого немає), це все одно не має сенсу.
Гонки легкості по орбіті

Другий абзац: поняття не маю, що ти намагаєшся сказати.
Гонки легкості по орбіті

@LightnessRacesinOrbit Я вважаю, що ця відповідь була результатом мого додавання до питання тегу [language-юрист]. Зараз я подумав про це краще (відповіді, як правило, занадто буквальні) і усунув це.
SS Anne

1
@ JL2210 Я не думаю, що це була твоя вина.
Гонки легкості по орбіті
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.