Domanda

In C non possiamo usare & per scoprire l'indirizzo di una variabile di registro ma in C++ possiamo fare lo stesso.Perché è legale in C++ ma non in C?Qualcuno può spiegare questo concetto in modo approfondito.

È stato utile?

Soluzione

Ecco un estratto dalla Sezione 6.7.1 (nota 101) del Norma C99 (pdf):

L'implementazione può trattare qualsiasi register dichiarazione semplicemente come an auto dichiarazione.Tuttavia, indipendentemente dal fatto che venga effettivamente utilizzata o meno l'archiviazione indirizzabile, l'indirizzo di qualsiasi parte di un oggetto dichiarato con il registro specificatore della classe di archiviazione non può essere calcolato, sia esplicitamente (tramite l'uso di unary & operatore come discusso in 6.5.3.2) o implicitamente (convertendo il nome di un array in un puntatore come discusso in 6.3.2.1).Pertanto, l'unico operatore che può essere applicato a un array dichiarato con l'identificatore della classe di archiviazione register È sizeof.

E dalla Sezione 7.1.1, Comma 3 del Norma C++ (pdf):

UN register specificatore ha la stessa semantica di an auto specificatore insieme ad un suggerimento per l'implementazione che l'oggetto così dichiarato sarà ampiamente utilizzato. [Nota:il suggerimento può essere ignorato e nella maggior parte delle implementazioni verrà ignorato se viene preso l'indirizzo dell'oggetto.—nota finale]

Curiosità divertenti su register

Il gruppo C++ (WG21) vuole deprecare register:

IL register La parola chiave ha pochissima funzione, offrendo solo un suggerimento che una nota dice che viene generalmente ignorata.Dovrebbe essere deprecato in questa versione dello standard, liberando il nome riservato per l'uso in uno standard futuro, proprio come auto è stato riutilizzato questa volta perché altrettanto inutile.

Appunti dall'incontro di marzo 2009:

Il consenso del CWG era a favore della deprecazione register.

Guarda cosa dice il gruppo C99 (WG14) detto circa register (PDF) ad un incontro:

Accordo generale per deprecare il “auto" parola chiave.Dovremmo chiedere a WG21 di tornare all'uso precedente di "register"(nessun indirizzo)?No, questo non funzionerà con WG21.

Altri suggerimenti

La parola chiave registro è solo un suggerimento e può essere ignorato. La maggior parte dei compilatori C ++ ignorano tutto il tempo, ma qualsiasi compilatore C ++ potranno ignorarlo se si prende l'indirizzo della variabile, o di creare un riferimento ad esso.

D'altra parte, un compilatore C ++ non sono di ignorare "registrare" solo perché si prende l'indirizzo della variabile. In teoria il compilatore potrebbe conservarlo in un registro e dare un certo valore puntatore magia che è in qualche modo associato al registro dietro le quinte, ma che sarebbe stato un sacco di lavoro per molto poco guadagno, in modo che nessun compilatore (che io sappia) fa una cosa del genere.

Dal registro è ignorabile in C così, ho il sospetto che la proscrizione esplicito contro la presa indirizzi delle variabili di registro era semplicemente quello di alleviare i compilatori C dal peso di controllo per questo.

La parte rilevante dello standard C ++ è 7.1.1.3:

  

Un identificatore di registro ha la stessa semantica come uno specificatore auto insieme con un accenno alla realizzazione che l'oggetto in modo dichiarato verrà utilizzato pesantemente. [Nota: il suggerimento può essere ignorato e nella maggior parte delle implementazioni verrà ignorato se è preso l'indirizzo dell'oggetto. Nota -end]

Ci scusiamo per la super tardi risposta.

Il problema è che, in C, register originariamente significava memorizzare i valori in un registro che è perché solo int e char possono essere utilizzati per esso. Ma con il tempo e soprattutto di serie C ++, è ampliato per "accesso rapido" piuttosto che "nel registro di CPU". Quindi, in C ++, una matrice forse un tipo register ma sappiamo che non è possibile memorizzare le matrici in un registro della CPU. Quindi, è logico giusto per affrontare un C ++ registrare (nel senso di cui sopra), ma sarà comunque alcun senso se i valori sono in realtà in un registro della CPU.

Suppongo che la parola chiave non avrebbe nemmeno fatto in lingua se non fosse per la compatibilità C. Mentre non posso parlare con qualsiasi autorità, se è così, mi sembra ci sia una ragione pratica per essere legale al di là di un semplice standard imposto "il compilatore è più intelligente di te" clausola: C ++ prende indirizzi delle cose senza permesso più facilmente di C fa. In particolare: le funzioni di membro, e riferimenti.

A causa funzioni membro richiedono un parametro this implicita, sarebbe impossibile chiamarli da un oggetto dichiarato register. In C, non c'è niente che vieta di dire register struct X x;, in modo tale linguaggio dovrebbe essere consentito in C ++ [dal C-compatibilità è tutta la ragione la parola esiste anche]. Ma se si vieta di chiamare funzioni membro nonché tenendo indirizzi, che copre anche la chiamata al costruttore iniziale. In sostanza, che non avrebbe funzionato sui tipi non-POD. Così si finisce con una classe di storage specificatore che è valida solo per un piccolo sottoinsieme dei tipi di legge, quando tutto il resto può essere utilizzato per qualsiasi cosa.

Non è inoltre possibile creare i riferimenti a tali oggetti, anche se, tecnicamente, il compilatore non ha bisogno di trattare i riferimenti come puntatori. register int i; int& x; non è richiesto di avere spazio per due variabili, ma se in seguito fai &x si finisce con un puntatore a i. Così il costrutto iniziale deve essere reso illegale. Anche se questo sembra un non-problema, dal momento che i riferimenti non esistono in C ogni caso, tornando al nostro punto precedente, i tipi POD dichiarate con l'identificatore register non possono più essere copiati. Il costruttore di copia compilatore fornito è della forma X::X(const X&) o X::X(X&) come appropriato.

Quindi, al fine di mantenere la compatibilità C, devono fare register unico come un identificatore di classe di archiviazione in quanto non si applica a tutti i tipi, e modificare almeno due parti diverse dello standard altrove [per specificare che si può non creare un riferimento a una variabile dichiarata con l'identificatore register, e di lavorare in qualche modo intorno i riferimenti per la copia POD]. Oppure, si potrebbe semplicemente dire "il suo bene a prendere l'indirizzo" e lasciare che i compilatori decidere se o non onorare le richieste. Qualcosa che stavano progettando di fare in ogni caso.

Una variabile registro non dispone di un indirizzo, è tenuto (almeno si suppone che si terrà) in un registro della CPU. Dal momento che il modificatore di registro non è altro che un suggerimento, se si forza il compilatore a generare codice per estrarre il suo indirizzo, il modificatore verrà ignorata e si finisce con una variabile regolare tenuta in memoria.

Per rispondere direttamente alla tua domanda, quale uno ti permette di prendere l'indirizzo di una variabile registro (il tuo post originale è in contraddizione con se stessa ..) consente di ignorare il proprio suggerimento e deve almeno emettere un avviso. IMO la corretta applicazione potrebbe essere quella di non consentire di prendere l'indirizzo di una variabile registro.

La cosa importante da ricordare è che "registro" è solo un suggerimento per il compilatore (uno inutile a questo; non ho mai visto alcun miglioramento della velocità, e la maggior parte dei compilatori probabilmente solo ignorarlo). C e C ++ sono entrambi autorizzati a ignorare il tuo "consigli" e mantenere la variabile in memoria. Naturalmente, se si prende l'indirizzo della variabile, esso costringerà ad assegnare un posto nella memoria.

C e C ++ appena hanno regole diverse su ciò che si può fare, perché sono diverse lingue. Il C ++ progettisti hanno deciso di consentire di ottenere l'indirizzo di una variabile registro perché non fa male niente; C non consente di farlo, perché costringerebbe in memoria.

A pensarci più, restrizione di C è probabilmente per la stessa ragione che le variabili dovevano essere dichiarati all'inizio del blocco-il compilatore in grado di layout di memoria per le variabili come li incontra, senza riguardo per come viene utilizzato in seguito nel la funzione.

Questa è solo un'ipotesi, ma dubito che si può prendere l'indirizzo di un registro in C ++ perché un tale pensare semplicemente non esiste. C ++, probabilmente non usa un registro nel vostro caso particolare. Si noti che la register classe di memorizzazione di qualificazione è solo un accenno al compilatore (e la maggior parte se non tutti i compilatori moderni felicemente ignorano completamente).

C e C ++ sono due lingue diverse, con un grande sottoinsieme comune. Ecco perché alcune cose sono diverse tra di loro.

Anche se non capisco la tua domanda, register è (almeno in C ++) un suggerimento che una variabile può essere letta con maggiore frequenza, e nulla più. In C, significa che non si può prendere l'indirizzo con il & operatore unario, che ha fatto una certa quantità di senso al tempo. Nei primi giorni di C, ci si aspettava che il compilatore potrebbe non preoccuparsi della memoria allocare per la variabile, e quindi non ci sarebbe necessariamente essere un indirizzo di prendere.

(computer hanno normalmente registri che sono parte di accesso rapido della CPU, e quindi la memorizzazione veloce per l'accesso. Una variabile possa vivere in un registro, anziché nella memoria, se che ha causato prestazioni migliori.)

Al giorno d'oggi, quasi tutti i compilatori sono abbastanza sofisticati per fare la propria allocazione di meglio che il programmatore può, in modo da utilizzare register è quasi sempre inutile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top