2013-07-06 17 views
14

Prendete questo codice:Quanto l'estensibilità della libreria standard C influisce sui programmi C++?

int issuecode(int i) 
{ 
    return 2 * i; 
} 

int main(int argc, char **argv) 
{ 
    return issuecode(argc); 
} 

Il modo in cui ho capito, se compilato come un programma C, avrà un comportamento indefinito. Ho ragione in base a standard di queste citazioni:

C99, 7,26 (o C11, 7,31)

I seguenti nomi sono raggruppate in singole intestazioni per convenienza. Tutti i nomi esterni descritti di seguito sono riservati, indipendentemente dalle intestazioni incluse nel programma.

C99, 7.26.2 (o C11, 7.31.2)

I nomi delle funzioni che iniziano con uno o isto, e una lettera minuscola può essere aggiunto alle dichiarazioni del <ctype.h> intestazione.

C99, 7.1.3 (o C11, 7.1.3)

  1. Ogni intestazione dichiara o definisce tutti gli identificatori elencati nella sottoclausola associato e opzionalmente dichiara o definisce identificatori elencati nella sua libreria delle direzioni future associate, subclause e identificatori che sono sempre riservati per qualsiasi uso o per uso come identificatori di scope di file.

    [...]

    • Tutti gli identificatori con collegamento esterno in uno qualsiasi dei seguenti sottoclausole (comprese le future direzioni della biblioteca) sono sempre riservati per l'uso come identificatori con collegamento esterno.
  2. [...] Se il programma dichiara o definisce un identificatore in un contesto in cui esso è riservata (non come consentito dalla 7.1.4), o definisce un identificatore riservata come un nome di macro, il il comportamento non è definito.

base a quanto sopra, credo che il nome della funzione issuecode è in realtà riservato per l'uso in <ctype.h>, e così il programma ha tecnicamente UB.

Domanda 0 (controllo di integrità): la mia lettura dello standard è corretta e il comportamento del programma non è definito tecnicamente?

Domanda 1: Il programma avrà UB se compilato come codice C++?

Credo che la risposta sia "no", come dalle citazioni seguenti, direi che "le future direzioni di libreria" di C non fanno parte della libreria standard C++, ma non ne sono proprio sicuro.

C++ 11, 21.7

  1. Tabelle 74, 75, 76, 77, 78 e 79 descrivono intestazioni <cctype>, <cwctype>, <cstring>, <cwchar>, <cstdlib> (conversioni carattere), e <cuchar>, rispettivamente.

  2. Il contenuto di questi connettori sono uguali alle intestazioni standard di C biblioteca <ctype.h>, <wctype.h>, <string.h>, <wchar.h>, e <stdlib.h> e l'intestazione C Unicode TR, rispettivamente, con le seguenti modifiche:

Nessuna delle "successive modifiche" menziona gli identificatori riservati aggiuntivi. La Tabella 74 è un elenco tassativo di nomi di funzioni come isdigit e isalnum.

C++ 11, C.2

1. Questa sottoclausola riassume il contenuto della libreria standard C++ incluso dalla libreria standard C. Riassume anche i cambiamenti espliciti nelle definizioni, dichiarazioni o comportamenti dalla libreria C standard annotata in altri subclaus (17.6.1.2, 18.2, 21.7).

7. La libreria standard C++ fornisce 209 funzioni standard dalla libreria C, come indicato nella tabella 153.

Nuovamente, tavolo 153 è una lista taxative.

Domanda 2: presupponendo io sono sbagliato su domanda 1 e il programma fa in realtà hanno UB in C++, così, sarebbe la seguente modifica influire su questo?

namespace foo { 

    int issuecode(int i) 
    { 
    return 2 * i; 
    } 

} 

using namespace foo; 

int main(int argc, char **argv) 
{ 
    return issuecode(argc); 
} 

Nota: Le citazioni standard sono prese da correnti d'aria N1256 (C99), N1570 (C11) e N3242 (C++ 11), che sono le più recenti bozze pubblicamente disponibili per la rispettiva lingua versioni.

+0

0. Partite di checksum. 1. Penso di sì, la libreria standard C++ ** contiene, come sottoinsieme ** tutta la libreria standard C (anche le vecchie intestazioni .h deprecate). 2. Penso di sì di nuovo, perché ora non ci si trova nello spazio dei nomi 'std ::'. (Il meglio sarebbe provarlo su un DS9K, però.) –

+1

+1, ma ... sul serio? Un programma C++ che contiene una funzione il cui nome inizia con 'is' ha UB? Se è così, ho scritto UB tutto il tempo ... –

+0

@AndyProwl Quelli erano i miei pensieri esattamente quando ho letto quella parte dello standard C. Ecco perché ho fatto questa domanda comunque. E tecnicamente, sono solo funzioni globali non statiche; motivo in più per usare gli spazi dei nomi ;-) – Angew

risposta

1

I seguenti nomi sono raggruppati in singole intestazioni per comodità. Tutti i nomi esterni descritti di seguito sono riservati, indipendentemente dalle intestazioni incluse nel programma.

C'è un elenco predefinito di funzioni che sono riservati, se la funzione non è in conflitto nome saggio non v'è alcun problema. nomi

funzione che iniziano con o è o, e una lettera minuscola possono essere aggiunti alle dichiarazioni del <ctype.h> intestazione.

Il termine operativo è possono essere aggiunto all'intestazione <ctype.h>. Il bit "è o per" è solo una guida per l'organizzazione delle dichiarazioni.

Quindi non c'è mai stato davvero un comportamento indefinito lì ...

Per quanto riguarda C++ Penso che questo segue la stessa idea Prendiamo ad esempio:

namespace foo{ 
    int isupper (int c); 
} 

#include <cctype> 
using namespace foo; 
int main(void){ 
    isupper(92); 
} 

che dovrebbe produrre un errore di compilazione perché la vostra funzione si scontra nome saggio con la funzione C, ma a causa dello spazio dei nomi questo è facilmente risolvibile aggiungendo uno std:: o uno foo:: all'inizio della chiamata.

+0

Non penso che tu abbia ragione sul fatto che esiste un "elenco predefinito di funzioni che sono riservate". La maggior parte di 7.26 ("Future library directions") è nella stessa vena del prefisso 'is' o' to'. Per esempio. "Macro che iniziano con' E' e una cifra, "" I nomi typedef iniziano con 'int' o' uint' e finiscono con '_t'." La clausola sarebbe quasi inutile se questi non fossero normativi, e sarebbe praticamente in contraddizione con il suo primo paragrafo. – Angew

+0

Trovo improbabile che lascino un tale foro UB nella specifica, in particolare non con funzioni verbali così ovvie in cui sarebbe altamente probabile che uno sviluppatore possa avere una funzione 'toFoo', sarebbe sciocco. – Mgetz

+0

Concordo sul fatto che suona un po 'troppo grande di nomi da riservare. Forse il significato previsto era "se l'implementazione aggiunge tali nomi, sono riservati anche quando l'intestazione non è inclusa?" Non lo legge in questo modo, ma forse avrebbe più senso ... – Angew

0

C++ 11 17.6.1.2 intestazioni

172) Il C intestazioni libreria standard (allegato D.5) definiscono anche i nomi nello spazio dei nomi globale, mentre le intestazioni per C le biblioteche C++ (17.6.1.2) potrebbe anche definire nomi all'interno dello spazio dei nomi globale.

Nella libreria standard C++, tuttavia, le dichiarazioni (ad eccezione dei nomi definiti come macro in C) rientrano nell'ambito dello spazio dei nomi (3.3.6) dello spazio dei nomi std. È non specificato se questi nomi vengono dichiarati per la prima volta nell'ambito dell'ambito dello spazio dei nomi globale e vengono quindi iniettati nello std dei nomi dalloutilizzando esplicitamente using-declaration (7.3.3).

Quindi se non si include <cctype> il comportamento è ben definito. Se lo fai, non è specificato.

+0

Se C99 7.26 appliesto C++, è indipendente dall'inclusione dell'intestazione (richiede 7.26).Se non si applica, non ci può essere UB in C++, perché quindi "" non riserva quei nomi aggiuntivi. Quindi, in un certo senso, il nocciolo della mia domanda era se C99 7.26 si applica a C++. IOW, quali sono "questi nomi" (dalla tua citazione). Non penso che la citazione si riferisca a questo. – Angew