¿Qué sucede si el comportamiento indefinido de C ++ cumple con el comportamiento definido de C?


10

Tengo un *.cpparchivo que compilo con C ++ (no un compilador de C). La función que contiene se basa en una conversión (vea la última línea) que parece estar definida en C (¡corrija si estoy equivocado!), Pero no en C ++ para este tipo especial.

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

Dado que compilo esto en un archivo C ++, ¿es este un comportamiento ahora definido o indefinido? ¿O necesitaría mover esto a un *.carchivo para definir su comportamiento?


1
La extensión del archivo no tiene significado; solo si lo compila como C o C ++.
Fredrik

1
Los tipos correspondientes no se heredan entre sí y no tienen relación y eso no está definido en C ++
Daniel Stephens

1
Normalmente, si el archivo tiene .cextensión, el compilador de C se invoca automáticamente.
Igor R.

1
Hago ese truco todo el tiempo en código C ++. No tengo idea de por qué no funcionará para ti. ¿Falta un encabezado en alguna parte?
user4581301

3
@DanielStephens Este programa nunca intenta desreferenciar el puntero. Se permite emitir en sí mismo , desreferenciar, solo a veces. Si el lado C devuelve el puntero correctamente al tipo real, entonces todo debería estar bien. Podrían ocurrir problemas con la fundición si esos tipos tuvieran requisitos de alineación diferentes.
user7860670

Respuestas:


6

Esto se define tanto en C ++ como en C. No viola las estrictas regulaciones de alias ya que no desreferencia el puntero resultante.

Aquí está la cita de C ++ (gracias a @interjay y @VTT) que permite esto:

Un puntero de objeto puede convertirse explícitamente en un puntero de objeto de un tipo diferente.

Aquí está la cita de C (gracias @StoryTeller) que permite esto:

Un puntero a un tipo de objeto puede convertirse en un puntero a un tipo de objeto diferente.

Estos especifican que un tipo de puntero se puede convertir a otro tipo de puntero (y luego, opcionalmente, volver a convertir) sin consecuencias.

Y aquí está la cita de POSIX que permite este caso específico:

La estructura sockaddr_in se usa para almacenar direcciones para la familia de direcciones de Internet. Los apuntadores a este tipo serán emitidos por aplicaciones para estructurar sockaddr * para su uso con funciones de socket.

Como esta función ( bind) es parte de la biblioteca estándar de C, lo que sea que ocurra dentro (específicamente, desreferenciar el puntero con tipo de letra) no tiene un comportamiento indefinido.


Para responder a la pregunta más general:

C y C ++ son dos lenguajes diferentes. Si algo se define en C pero no en C ++, se define en C pero no en C ++. Ninguna compatibilidad implícita entre los dos idiomas cambiará eso. Si desea utilizar código bien definido en C pero indefinido en C ++, deberá utilizar un compilador de C para compilar ese código.


1
@interjay ¿Puede respaldar eso con una cita del estándar (C o C ++ está bien)?
SS Anne


1
@StoryTeller Gracias. Sin embargo, se agregó la versión HTTP.
SS Anne

2
Podría decirse que este es un defecto en el estándar POSIX: el segundo argumento binddebe ser a const void *, pero bindes anterior a la existencia del voidlenguaje C (y la existencia de C ++). Lo actualizaron en algún momento para agregar const, pero nunca arreglaron el tipo básico.
Chris Dodd

1
Puedo recomendar esta charla youtube.com/watch?v=_qzMpk-22cc Todavía no estoy seguro de si valida la respuesta, o si en realidad dice lo contrario: -o C ++ es una pesadilla ... jajaja
Daniel Stephens

-3

Todas las llamadas entre código C y C ++ invocan Comportamiento indefinido, desde el punto de vista de los estándares respectivos, pero la mayoría de las plataformas especifican tales cosas.

En situaciones en las que partes del Estándar C o C ++ y la documentación de una implementación definen o describen conjuntamente una acción, pero otras partes la caracterizan como Indefinida, las implementaciones pueden procesar código de la manera que mejor satisfaga las necesidades de sus clientes o, si son indiferentes a las necesidades del cliente, sea cual sea la moda que consideren adecuada. El hecho de que el Estándar considere tales asuntos como ajenos a su jurisdicción no implica ningún juicio sobre cuándo y / o cómo las implementaciones que afirman su idoneidad para diversos fines deben procesarlos de manera significativa, pero algunos encargados de la compilación suscriben un mito que sí lo hace.


Primer párrafo: "Todas las llamadas entre el código C y C ++ invocan un comportamiento indefinido" Incluso si existiera algo como "invocar un comportamiento indefinido" (que no existe), esto todavía no tiene sentido.
Carreras de ligereza en órbita

Segundo párrafo: no tengo idea de lo que estás tratando de decir.
Carreras de ligereza en órbita

@LightnessRacesinOrbit Creo que esta respuesta fue el resultado de haber agregado la etiqueta [language-lawyer] a la pregunta. Ahora lo he pensado mejor (las respuestas tienden a ser demasiado literales) y lo eliminé.
SS Anne

1
@ JL2210 No creo que haya sido culpa tuya.
Carreras ligeras en órbita el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.