2011-09-28 12 views
9

Ho provato questo in GCC 4.6 e si compila e collega, ma dà un messaggio "errore bus" su runtime su MacOS. VS2010 non lo compila nemmeno.È corretto questo codice C++ 0x?

Ma la domanda è, se ciò effettivamente lavorare in serie C++ 0x?

#include <cstdio> 
int (*main)()=[]()->int{printf("HEY!\n");return 0;}; 

Sì, quello che sta cercando di fare è definire "main" come funzione lambda.

+13

Mi piace il modo in cui stai cercando di utilizzare le ultime funzionalità avanzate di C++ 11, ma continuo a utilizzare 'cstdio' e' printf' :-) – paxdiablo

+4

@paxdiablo: printf rocks !!! C++ fallito ai flussi I/O :) –

+1

Secondo Stroustroup ... se C ti permette di sparare ai piedi, C++ può far saltare tutte le gambe! Questo è quello che chiamo ... masochismo! :-)) –

risposta

14

Questo non è un programma C++ valido, poiché il simbolo main non è definito come una funzione, ma piuttosto un puntatore alla funzione. Ecco perché si verifica un errore di segmentazione: il runtime sta tentando di eseguire un puntatore.

+0

+1: (Rimosso il mio commento sciatta alla domanda iniziale Quella risposta sorta di meglio spiega che cosa sta accadendo qui..) –

+0

allora credo che in realtà è un bug nel GCC che accetta questo codice come corretto? – hasvn

+0

@hasvn, non ne sono sicuro, ma penso che questo sia uno di quei casi in cui non è richiesta alcuna diagnostica dallo standard. Quindi gcc potrebbe essere in chiaro. – avakar

3

No, questo non è corretto.

Main è una funzione speciale e richiede rigidi requisiti (anche più severi di una funzione normale), ma si crea anche una certa confusione tra cosa è una funzione e cosa è un puntatore a una funzione.

Il problema logica è che c'è una differenza tra una funzione e una variabile in possesso di un puntatore a una funzione (quello che si vuole principale di essere). Una funzione ha un indirizzo fisso in memoria, quindi per chiamare una funzione viene chiamato semplicemente l'indirizzo. Un puntatore a una funzione punti in un indirizzo in memoria, quindi per chiamare la funzione è necessario prima leggere ciò che il puntatore punta e quindi chiamare quell'indirizzo.

Un puntatore a funzione ha un diverso livello di riferimento indiretto da una funzione.

La sintassi è lo stesso ... cioè se x è un puntatore a una funzione si può scrivere x(42), ma ancora il codice macchina generato è differente se x è invece una funzione (nel caso di un puntatore un valore deve essere cercato e l'indirizzo di chiamata è determinato in fase di esecuzione, con una funzione l'indirizzo è fissato - fino al trasferimento - ed è determinato al momento del collegamento).

0

Per la portabilità tra i compilatori e le implementazioni di libreria standard, printf() deve essere std :: printf() quando #including <cstdio>. E le altre cose sul main non valido().

+0

No, non è specificato nello standard se 'cXXX' include inject nello spazio dei nomi globale. È _wise_ usare 'std ::' ma "must" è probabilmente un overkill. – paxdiablo

+0

OK, questo era un mezzo scherzo comunque. Modificherò la risposta per notare che è richiesta per la portabilità. (Chi di noi scrive codice portatile per vivere comincia a pensare in questo modo ...) –

0

Ora, non dovrebbe nemmeno compilarlo. L'espressione lambda produce un tipo (un functor). Non c'è alcuna conversione implicita da tipo a puntatore a funzione.

A seconda del compilatore, la funzione main può avere collegamento C++ o C (è definita dall'implementazione). L'espressione Lambda restituisce il tipo C++ con l'operatore di chiamata di funzione, quindi il collegamento C++.

+0

Esiste effettivamente una conversione implicita da un lambda non di cattura a un puntatore di funzione. – avakar

+0

Citazione: (5.1.2/6). –

+0

Entrambi avete ragione. Tuttavia, converte implicitamente in puntatore alla funzione membro, non in una funzione libera. Ricordare vagamente questo potrebbe aver confuso me. – mloskot