Que se passe-t-il si un comportement C ++ non défini rencontre un comportement défini C?

10

J'ai un *.cppfichier que je compile avec C ++ (pas un compilateur C). La fonction contenant repose sur un cast (voir dernière ligne) qui semble être défini en C (veuillez corriger si je me trompe!), Mais pas en C ++ pour ce type spécial.

[...] 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 [...]

Puisque je compile ceci dans un fichier C ++, est-ce que ce comportement est maintenant défini ou non défini? Ou aurais-je besoin de déplacer cela dans un *.cfichier, pour en faire un comportement défini?

Daniel Stephens
la source
1
L'extension de fichier n'a aucune signification; uniquement si vous le compilez en C ou C ++.
Fredrik
1
Les types correspondants ne sont pas hérités les uns des autres et n'ont aucune relation et cela n'est pas défini en C ++
Daniel Stephens
1
En règle générale, si le fichier a une .cextension, le compilateur C est appelé automatiquement.
Igor R.
1
Je fais cette astuce tout le temps en code C ++. Aucune idée pourquoi cela ne fonctionnera pas pour vous. Vous manquez un en-tête quelque part?
user4581301
3
@DanielStephens Ce programme n'essaye jamais de déréférencer le pointeur. Le casting lui-même est autorisé , le déréférencement - seulement parfois. Si le côté C renvoie correctement le pointeur au type réel, tout devrait bien se passer. Des problèmes de moulage pourraient survenir si ces types avaient des exigences d'alignement différentes.
user7860670

Réponses:

6

Ceci est défini à la fois en C ++ et en C. Il ne viole pas les règles strictes d'alias car il ne déréférence pas le pointeur résultant.

Voici la citation de C ++ (grâce à @interjay et @VTT) qui permet cela:

Un pointeur d'objet peut être explicitement converti en un pointeur d'objet d'un type différent.

Voici la citation de C (merci @StoryTeller) qui permet cela:

Un pointeur vers un type d'objet peut être converti en pointeur vers un type d'objet différent.

Ceux-ci spécifient qu'un type de pointeur peut être converti en un autre type de pointeur (puis éventuellement reconverti) sans conséquence.

Et voici la citation de POSIX qui permet ce cas spécifique:

La structure sockaddr_in est utilisée pour stocker des adresses pour la famille d'adresses Internet. Les pointeurs vers ce type doivent être convertis par des applications en struct sockaddr * pour une utilisation avec les fonctions socket.

Comme cette fonction ( bind) fait partie de la bibliothèque standard C, tout ce qui se passe à l'intérieur (en particulier, déréférencer le pointeur transtypé) n'a pas de comportement non défini.


Pour répondre à la question plus générale:

C et C ++ sont deux langages différents. Si quelque chose est défini en C mais pas en C ++, il est défini en C mais pas en C ++. Aucune compatibilité implicite entre les deux langues ne changera cela. Si vous souhaitez utiliser du code bien défini en C mais non défini en C ++, vous devrez utiliser un compilateur C pour compiler ce code.

SS Anne
la source
1
@interjay Pouvez-vous sauvegarder cela avec une citation de la norme (C ou C ++ est très bien)?
SS Anne
1
Et voilà port70.net/~nsz/c/c11/n1570.html#6.3.2.3p7
StoryTeller - Unslander Monica
1
@StoryTeller Merci. Cependant, la version HTTP a été ajoutée.
SS Anne
2
On peut dire que c'est un défaut dans la norme POSIX - le deuxième argument binddevrait être un const void *, mais bindest antérieur à l'existence de voiddans le langage C (et à l'existence de C ++ du tout). Ils l'ont mis à jour à un moment donné pour ajouter le const, mais n'ont jamais fixé le type de base.
Chris Dodd
1
Je peux recommander cet exposé youtube.com/watch?v=_qzMpk-22cc Je ne sais toujours pas s'il valide la réponse, ou s'il dit en fait le contraire: -o C ++ est un cauchemar .. lol
Daniel Stephens
-3

Les appels entre le code C et C ++ invoquent tous un comportement indéfini, du point de vue des normes respectives, mais la plupart des plateformes spécifient de telles choses.

Dans les situations où des parties de la norme C ou C ++ et la documentation d'une implémentation définissent ou décrivent ensemble une action, mais que d'autres parties la caractérisent comme non définie, les implémentations sont autorisées à traiter le code de la manière qui répondrait le mieux aux besoins de leurs clients ou - si elles sont indifférents aux besoins des clients - quelle que soit la mode qu'ils jugent appropriée. Le fait que la Norme considère ces questions comme ne relevant pas de leur juridiction n'implique aucun jugement quant au moment et / ou à la manière dont les implémentations revendiquant l'adéquation à diverses fins devraient être censées les traiter de manière significative, mais certains responsables du compilateur souscrivent à un mythe selon lequel il le fait.

supercat
la source
Premier paragraphe: "Les appels entre le code C et C ++ invoquent tous un comportement indéfini " Même s'il existait une chose telle que "invoquer un comportement indéfini" (ce qui n'est pas le cas), cela n'a toujours aucun sens.
Courses de légèreté en orbite
Deuxième paragraphe: aucune idée de ce que vous essayez de dire.
Courses de légèreté en orbite
@LightnessRacesinOrbit Je pense que cette réponse est le résultat de mon ajout de la balise [langue-avocat] à la question. J'ai maintenant pensé mieux (les réponses ont tendance à être bien trop littérales) et je l'ai supprimé.
SS Anne
1
@ JL2210 Je ne pense pas que ce soit votre faute.
Courses de légèreté en orbite