Preprocessori Objective-C

Il Objective-C Preprocessornon fa parte del compilatore, ma è un passaggio separato nel processo di compilazione. In termini semplicistici, un preprocessore Objective-C è solo uno strumento di sostituzione del testo e istruisce il compilatore a eseguire la pre-elaborazione richiesta prima della compilazione effettiva. Faremo riferimento al preprocessore Objective-C come OCPP.

Tutti i comandi del preprocessore iniziano con un simbolo cancelletto (#). Deve essere il primo carattere non vuoto e, per leggibilità, una direttiva per il preprocessore dovrebbe iniziare nella prima colonna. La sezione seguente elenca tutte le direttive importanti per il preprocessore:

Sr.No. Direttiva e descrizione
1

#define

Sostituisce una macro del preprocessore

2

#include

Inserisce una particolare intestazione da un altro file

3

#undef

Annulla la definizione di una macro del preprocessore

4

#ifdef

Restituisce vero se questa macro è definita

5

#ifndef

Restituisce vero se questa macro non è definita

6

#if

Verifica se una condizione del tempo di compilazione è vera

7

#else

L'alternativa per #if

8

#elif

#else an #if in una dichiarazione

9

#endif

Termina il condizionale del preprocessore

10

#error

Stampa un messaggio di errore su stderr

11

#pragma

Emette comandi speciali al compilatore utilizzando un metodo standardizzato

Esempi di preprocessori

Analizza i seguenti esempi per comprendere le varie direttive.

#define MAX_ARRAY_LENGTH 20

Questa direttiva dice all'OCPP di sostituire le istanze di MAX_ARRAY_LENGTH con 20. Usa #define per le costanti per aumentare la leggibilità.

#import <Foundation/Foundation.h>
#include "myheader.h"

Queste direttive indicano all'OCPP di ottenere foundation.h da Foundation Frameworke aggiungi il testo al file sorgente corrente. La riga successiva dice a OCPP di otteneremyheader.h dalla directory locale e aggiungere il contenuto al file di origine corrente.

#undef  FILE_SIZE
#define FILE_SIZE 42

Questo dice a OCPP di annullare la definizione di FILE_SIZE esistente e definirlo come 42.

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

Questo dice all'OCPP di definire MESSAGGIO solo se MESSAGGIO non è già definito.

#ifdef DEBUG
   /* Your debugging statements here */
#endif

Questo dice all'OCPP di eseguire il processo con le istruzioni incluse se DEBUG è definito. Questo è utile se passi il flag -DDEBUG al compilatore gcc al momento della compilazione. Questo definirà DEBUG, quindi puoi attivare e disattivare il debug al volo durante la compilazione.

Macro predefinite

ANSI C definisce un numero di macro. Sebbene ciascuno sia disponibile per l'uso nella programmazione, le macro predefinite non devono essere modificate direttamente.

Sr.No. Macro e descrizione
1

__DATE__

La data corrente come valore letterale carattere nel formato "MMM GG AAAA"

2

__TIME__

L'ora corrente come carattere letterale nel formato "HH: MM: SS"

3

__FILE__

Contiene il nome del file corrente come stringa letterale.

4

__LINE__

Contiene il numero di riga corrente come costante decimale.

5

__STDC__

Definito come 1 quando il compilatore è conforme allo standard ANSI.

Proviamo il seguente esempio:

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"File :%s\n", __FILE__ );
   NSLog(@"Date :%s\n", __DATE__ );
   NSLog(@"Time :%s\n", __TIME__ );
   NSLog(@"Line :%d\n", __LINE__ );
   NSLog(@"ANSI :%d\n", __STDC__ );
   
   return 0;
}

Quando il codice sopra in un file main.m viene compilato ed eseguito, produce il seguente risultato:

2013-09-14 04:46:14.859 demo[20683] File :main.m
2013-09-14 04:46:14.859 demo[20683] Date :Sep 14 2013
2013-09-14 04:46:14.859 demo[20683] Time :04:46:14
2013-09-14 04:46:14.859 demo[20683] Line :8
2013-09-14 04:46:14.859 demo[20683] ANSI :1

Operatori del preprocessore

Il preprocessore Objective-C offre i seguenti operatori per aiutarti nella creazione di macro:

Continuazione macro (\)

Di solito una macro deve essere contenuta su una singola riga. L'operatore di continuazione della macro viene utilizzato per continuare una macro troppo lunga per una singola riga. Ad esempio:

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!\n")

Stringize (#)

L'operatore stringize o number-sign ('#'), se utilizzato all'interno di una definizione di macro, converte un parametro macro in una costante di stringa. Questo operatore può essere utilizzato solo in una macro che ha un argomento o un elenco di parametri specificato. Ad esempio:

#import <Foundation/Foundation.h>

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Carole, Debra);
   return 0;
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

2013-09-14 05:46:14.859 demo[20683] Carole and Debra: We love you!

Token Incolla (##)

L'operatore di incolla token (##) all'interno di una definizione di macro combina due argomenti. Consente di unire due token separati nella definizione della macro in un unico token. Ad esempio:

#import <Foundation/Foundation.h>

#define tokenpaster(n) NSLog (@"token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   
   tokenpaster(34);
   return 0;
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

2013-09-14 05:48:14.859 demo[20683] token34 = 40

Come è successo, perché questo esempio si traduce nel seguente output effettivo dal preprocessore:

NSLog (@"token34 = %d", token34);

Questo esempio mostra la concatenazione del token ## n in token34 e qui abbiamo usato entrambi stringize e token-pasting.

L'operatore defined ()

Il preprocessore definedL'operatore viene utilizzato nelle espressioni costanti per determinare se un identificatore è definito utilizzando #define. Se l'identificatore specificato è definito, il valore è vero (diverso da zero). Se il simbolo non è definito, il valore è falso (zero). L'operatore definito è specificato come segue:

#import <Foundation/Foundation.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   NSLog(@"Here is the message: %s\n", MESSAGE);  
   return 0;
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

2013-09-14 05:48:19.859 demo[20683] Here is the message: You wish!

Macro parametrizzate

Una delle potenti funzioni di OCPP è la capacità di simulare funzioni utilizzando macro parametrizzate. Ad esempio, potremmo avere un codice per quadrare un numero come segue:

int square(int x) {
   return x * x;
}

Possiamo riscrivere il codice sopra usando una macro come segue:

#define square(x) ((x) * (x))

Le macro con argomenti devono essere definite utilizzando l'estensione #defineprima che possano essere utilizzati. L'elenco degli argomenti è racchiuso tra parentesi e deve seguire immediatamente il nome della macro. Non sono consentiti spazi tra il nome della macro e le parentesi aperte. Ad esempio:

#import <Foundation/Foundation.h>

#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
   NSLog(@"Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

2013-09-14 05:52:15.859 demo[20683] Max between 20 and 10 is 20