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?


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.


1
@interjay Pouvez-vous sauvegarder cela avec une citation de la norme (C ou C ++ est très bien)?
SS Anne


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.


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.