2010-04-16 8 views
6

Ho un problema, in quanto il seguente codice si descrive da solo.
È possibile ottenere il lineno che si chiama da solo? (C/C++)

1 #include<stdlib.h> 
2 #include<stdio.h> 
3 void log() 
4 { 
5   printf("Log [Line:%d]\n",__LINE__); 
6 } 
7 int main() 
8 { 
9   log(); 
10  log(); 
11 } 

Il risultato atteso è
Log [Linea: 9]
Log [Linea: 10]
Ma, il fatto è
Log [Linea: 5]
Log [Linea: 5 ]

No sorprendente, LINE è stato sostituito durante la fase di pre-processo come 5.
la mia domanda è , come progettare la funzione di registro per ottenere il risultato previsto?
Grazie!

risposta

15

è necessario scrivere una macro:

#define LOG printf("Log [Line:%d]\n",__LINE__) 

poi lo usano:

int main() { 
    LOG; 
    LOG; 
} 

Questo funziona perché la macro viene espansa al suo punto di utilizzo, dando la macro il valore corretto __LINE__.

+0

Nel caso di C++, si potrebbe anche utilizzare una funzione inline. – waffleman

+3

@waffleman No non è possibile - l'espansione delle macro (della macro '__LINE__') avviene prima che il compilatore veda il codice. –

+0

Una funzione inline non funzionerà - '__LINE__' è una macro del preprocessore, quindi viene sostituita durante il preprocessore, non durante la funzione di inlining. (modifica: ninja'd) – AshleysBrain

4

Una macro può superare questo, passando il __LINE__ come parametro per la funzione invocata.

Un altro approccio, forse complementare, è quello di passare un contesto alla funzione come parametro, con un valore predefinito che dice 'usa il numero di riga'. Ciò è dimostrato dal questo frammento di codice che sta facendo movimentazione con il modello di errore:

int read_byte(FILE* f,int line=0) { 
    int ret = fgetc(f); 
    if(-1 == ret) 
    throw (line? line: __LINE__); 
    return ret; 
} 

int read_uint16(FILE* f,int line=0) { 
    int hi = read_byte(f,(line? line: __LINE__)); 
    int lo = read_byte(f,(line? line: __LINE__)); 
    return (hi<<8)|lo; 
} 

int main() { 
    ... 
    try { 
    int i = read_uint16(f,__LINE__); 
    } catch(int line) { 
    fprintf(stderr,"Error at line %d\n",line); 
    } 
    ... 
} 

Infine, tutto questo sa di voler ottenere una traccia dello stack su C/codice C++ (soprattutto nel caso di movimentazione di errore). Guardate VALGRIND_PRINTF_BACKTRACE(format, ...)

1

È possibile modificare la funzione esistente leggermente e avvolgerlo in una macro:

#include<stdlib.h> 
#include<stdio.h> 

#define log() real_log(__LINE__) 

void real_log(int line) 
{ 
     printf("Log [Line:%d]\n", line); 
} 

int main() 
{ 
     log(); 
     log(); 
} 
Problemi correlati