Cosa succede se il comportamento C ++ non definito incontra il comportamento definito C?


10

Ho un *.cppfile che compilo con C ++ (non un compilatore C). La funzione contenitiva si basa su un cast (vedi l'ultima riga) che sembra essere definito in C (per favore correggi se sbaglio!), Ma non in C ++ per questo tipo speciale.

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

Dal momento che lo compilo in un file C ++, questo comportamento è ora definito o indefinito? O avrei bisogno di spostarlo in un *.cfile, per renderlo un comportamento definito?


1
L'estensione del file non ha significato; solo se lo compili come C o C ++.
Fredrik,

1
I tipi corrispondenti non sono ereditati l'uno dall'altro e non hanno alcuna relazione e ciò non è definito in C ++
Daniel Stephens,

1
In genere, se il file ha .cestensione, il compilatore C viene richiamato automaticamente.
Igor R.,

1
Faccio sempre quel trucco nel codice C ++. Non ho idea del perché non funzionerà per te. Manca un colpo di testa da qualche parte?
user4581301

3
@DanielStephens Questo programma non tenta mai di dereferenziare il puntatore. Cast stesso è permesso , dereferenziazione - solo a volte. Se il lato C riporta correttamente il puntatore al tipo reale, allora tutto dovrebbe andare bene. Potrebbero verificarsi problemi con la fusione se quei tipi avessero requisiti di allineamento diversi.
user7860670,

Risposte:


6

Questo è definito sia in C ++ che in C. Non viola le rigide normative di aliasing in quanto non dereferisce il puntatore risultante.

Ecco la citazione da C ++ (grazie a @interjay e @VTT) che consente questo:

Un puntatore oggetto può essere esplicitamente convertito in un puntatore oggetto di un tipo diverso.

Ecco la citazione di C (grazie a @StoryTeller) che consente questo:

Un puntatore a un tipo di oggetto può essere convertito in un puntatore a un diverso tipo di oggetto.

Questi specificano che un tipo di puntatore può essere convertito in un altro tipo di puntatore (e quindi facoltativamente riconvertito) senza conseguenze.

Ed ecco la citazione da POSIX che consente questo caso specifico:

La struttura sockaddr_in viene utilizzata per memorizzare gli indirizzi per la famiglia di indirizzi Internet. I puntatori di questo tipo devono essere lanciati dalle applicazioni per strutturare sockaddr * per l'uso con le funzioni socket.

Poiché questa funzione ( bind) fa parte della libreria standard C, qualunque cosa accada all'interno (in particolare, dereferenziando il puntatore del tipo cast) non ha un comportamento indefinito.


Per rispondere alla domanda più generale:

C e C ++ sono due lingue diverse. Se qualcosa è definito in C ma non in C ++, è definito in C ma non in C ++. Nessuna compatibilità implicita tra le due lingue lo cambierà. Se vuoi usare un codice ben definito in C ma non definito in C ++, dovrai usare un compilatore C per compilare quel codice.


1
@interjay Puoi supportarlo con una citazione dallo standard (o C o C ++ va bene)?
SS Anne,


1
@StoryTeller Grazie. Aggiunta invece la versione HTTP.
SS Anne,

2
Probabilmente questo è un difetto nello standard POSIX - il secondo argomento binddovrebbe essere a const void *, ma bindprecede l'esistenza di voidnel linguaggio C (e l'esistenza di C ++). Lo hanno aggiornato ad un certo punto per aggiungere il const, ma non hanno mai corretto il tipo di base.
Chris Dodd,

1
Posso consigliare questo discorso su youtube.com/watch?v=_qzMpk-22cc Non sono ancora sicuro se convalida la risposta o se in realtà sta dicendo il contrario: -o C ++ è un incubo .. lol
Daniel Stephens

-3

Le chiamate tra codice C e C ++ invocano tutte Undefined Behaviour, dal punto di vista dei rispettivi standard, ma la maggior parte delle piattaforme specifica tali cose.

In situazioni in cui parti dello standard C o C ++ e la documentazione di un'implementazione definiscono o descrivono insieme un'azione, ma altre parti lo caratterizzano come Non definito, le implementazioni sono autorizzate a elaborare il codice in qualunque modo servirebbe meglio le esigenze dei loro clienti o - se sono indifferenti alle esigenze dei clienti, qualunque sia la moda che ritengano opportuno. Il fatto che lo Standard consideri tali questioni al di fuori della loro giurisdizione non implica alcun giudizio su quando e / o in che modo le implementazioni che rivendicano l'idoneità per vari scopi debbano essere trattate in modo significativo, ma alcuni manutentori del compilatore sottoscrivono un mito che lo fa.


Primo paragrafo: "Le chiamate tra il codice C e C ++ invocano tutte comportamenti indefiniti" Anche se esisteva qualcosa come "invocare comportamenti indefiniti" (che non esiste), ciò non ha ancora senso.
Razze di leggerezza in orbita

Secondo paragrafo: non ho idea di cosa stai cercando di dire.
Razze di leggerezza in orbita

@LightnessRacesinOrbit Penso che questa risposta sia stata il risultato della mia aggiunta del tag [avvocato-lingua] alla domanda. Ora ci ho pensato meglio (le risposte tendono ad essere troppo letterali) e l'ho rimosso.
SS Anne,

1
@ JL2210 Non credo sia stata colpa tua.
Razze di leggerezza in orbita
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.