O que acontece se o comportamento indefinido do C ++ atender ao comportamento definido pelo C?

10

Eu tenho um *.cpparquivo que eu compilar com C ++ (não um compilador C). A função contendo depende de uma conversão (consulte a última linha) que parece ser definida em C (corrija se estiver errado!), Mas não em 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 [...]

Desde que eu compilo isso em um arquivo C ++, isso agora é um comportamento definido ou indefinido? Ou eu precisaria mover isso para um *.carquivo, para torná-lo um comportamento definido?

Daniel Stephens
fonte
11
A extensão do arquivo não tem significado; somente se você compilar como um C ou C ++.
Fredrik
11
Os tipos correspondentes não são herdadas um do outro e não têm nenhuma relação, e que é indefinido em C ++
Daniel Stephens
11
Normalmente, se o arquivo tiver .cextensão, o compilador C é chamado automaticamente.
Igor R.
11
Eu faço esse truque o tempo todo no código C ++. Não faço ideia por que não funcionará para você. Está faltando um cabeçalho em algum lugar?
User4581301
3
@DanielStephens Este programa nunca tenta remover a referência do ponteiro. O elenco em si é permitido , sem referência - apenas algumas vezes. Se o lado C repassar corretamente o ponteiro para o tipo real, tudo ficará bem. Podem ocorrer problemas com o vazamento se esses tipos tiverem requisitos de alinhamento diferentes.
user7860670

Respostas:

6

Isso é definido em C ++ e C. Ele não viola os regulamentos estritos de alias, pois não desrefere o ponteiro resultante.

Aqui está a citação do C ++ (graças a @interjay e @VTT) que permite isso:

Um ponteiro de objeto pode ser explicitamente convertido em um ponteiro de objeto de um tipo diferente.

Aqui está a citação de C (obrigado @StoryTeller) que permite isso:

Um ponteiro para um tipo de objeto pode ser convertido em um ponteiro para um tipo de objeto diferente.

Eles especificam que um tipo de ponteiro pode ser convertido em outro tipo de ponteiro (e opcionalmente convertido de volta) sem conseqüências.

E aqui está a citação do POSIX que permite este caso específico:

A estrutura sockaddr_in é usada para armazenar endereços para a família de endereços da Internet. Ponteiros para esse tipo devem ser convertidos por aplicativos para estruturar sockaddr * para uso com funções de soquete.

Como essa função ( bind) faz parte da biblioteca padrão C, o que quer que ocorra dentro (especificamente, desreferenciando o ponteiro de conversão de tipo) não possui um comportamento indefinido.


Para responder à pergunta mais geral:

C e C ++ são duas linguagens diferentes. Se algo é definido em C, mas não em C ++, é definido em C, mas não em C ++. Nenhuma compatibilidade implícita entre os dois idiomas mudará isso. Se você deseja usar código bem definido em C, mas não definido em C ++, será necessário usar um compilador C para compilar esse código.

SS Anne
fonte
11
@interjay Você pode fazer backup disso com uma cotação do padrão (C ou C ++ está bom)?
SS Anne
11
Lá você vai port70.net/~nsz/c/c11/n1570.html#6.3.2.3p7
StoryTeller - Unslander Monica
11
@StoryTeller Obrigado. Adicionada a versão HTTP, no entanto.
SS Anne
2
Indiscutivelmente, esse é um defeito no padrão POSIX - o segundo argumento binddeve ser a const void *, mas bindantecede a existência da voidlinguagem C (e a existência de C ++). Eles o atualizaram em algum momento para adicionar o const, mas nunca corrigiram o tipo básico.
Chris Dodd
11
Posso recomendar essa palestra youtube.com/watch?v=_qzMpk-22cc Ainda não tenho certeza se ela valida a resposta ou se está realmente dizendo o contrário: -o C ++ é um pesadelo .. lol
Daniel Stephens
-3

Todas as chamadas entre códigos C e C ++ invocam o comportamento indefinido, do ponto de vista dos respectivos padrões, mas a maioria das plataformas especifica essas coisas.

Em situações em que partes do padrão C ou C ++ e a documentação de uma implementação definem ou descrevem uma ação juntas, mas outras partes a caracterizam como Indefinida, as implementações têm permissão para processar código da maneira que melhor atenda às necessidades de seus clientes ou - se eles são indiferentes às necessidades dos clientes - da maneira que acharem melhor. O fato de a Norma considerar assuntos fora de sua jurisdição não implica julgamento sobre quando e / ou como as implementações que reivindicam adequação para vários propósitos devem processá-las de maneira significativa, mas alguns mantenedores do compilador subscrevem o mito de que são.

supercat
fonte
Primeiro parágrafo: "Chamadas entre código C e C ++ invocam comportamento indefinido" Mesmo que existisse algo como "invocar comportamento indefinido" (o que não existe), isso ainda não faz sentido.
Lightness Races em órbita
Segundo parágrafo: não faço ideia do que você está tentando dizer.
Lightness Races em órbita
@LightnessRacesinOrbit Acho que essa resposta foi resultado da adição da tag [language-advogado] à pergunta. Agora pensei melhor (as respostas tendem a ser literais demais) e o removi.
SS Anne
11
@ JL2210 Eu não acho que foi sua culpa.
Lightness Races em órbita