2013-04-19 19 views
16

Nel linguaggio C, __FUNCTION__ può essere utilizzato per ottenere il corrente nome della funzione. Ma se io definisco una funzione denominata un() e viene chiamato in B(), come di seguito:Come possiamo conoscere il nome della funzione del chiamante?

b() 
{ 
    a(); 
} 

Ora, nel codice sorgente, ci sono un sacco di funzioni come B() che chiamano un (), per esempio c(), d(), e() ...

E 'possibile, all'interno di a(), aggiungere un codice per rilevare il nome della funzione che ha chiamato a()?

Ulteriori:

  1. Ci scusiamo per l'errore di battitura fuorviante. L'ho corretto
  2. Sto cercando di scoprire quale funzione chiama a() per scopi di debug. I non so come si fa nella stessa situazione?
  3. E il mio codice è in vxWorks, ma non sono sicuro che sia correlato a C99 o altro.
+0

Non è sicuro. Ma [questo] (http://stackoverflow.com/questions/2154852/get-a-pointer-to-the-current-function-in-c-gcc) potrebbe esserti d'aiuto –

+0

Perché vuoi farlo? E 'per scopi di debug? – fstamour

+0

Se questo è solo per il debug, è possibile definire un come macro, in questo modo l'uso di '__func__' restituirà b, come si desidera. – Joe

risposta

33

Non c'è niente che puoi fare solo in a.

Tuttavia, con un semplice trucco macro, è possibile ottenere ciò che si desidera, IIUC che mostra il nome del chiamante.

void a() 
{ 
    /* Your code */ 
} 

void a_special(char const * caller_name) 
{ 
    printf("a was called from %s", caller_name); 
    a(); 
} 

#define a() a_special(__FUNC__) 

void b() 
{ 
    a(); 
} 
+0

Ho dovuto dichiarare la variabile caller_name come 'const char * caller_name', ma ha funzionato! – redcurry

+0

Precisione: '__func__' fa parte dello standard C99, [...]' __FUNCTION__' è un altro nome per '__func__', fornito per retrocompatibilità con le vecchie versioni di GCC. (fonte: https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html) –

0

È possibile contrassegnare ogni funzione che chiama un() con un identificatore intero che viene passato un() come parametro e quindi utilizzare un switch-case costrutto un() dire quale funzione ha invocato un() .A printf() direbbe quale funzione invocata un() seconda del valore identificatore intero se si utilizza come argomento ad uno switch-case costrutto in un ()

#include<stdio.h> 

void a(int); 
void b(); 
void c(); 
void d(); 

int main(void) 
{ 

b(); 
c(); 
d(); 

} 

void b() 
{ 

int x=1; 
a(x); 

} 

void c() 
{ 

int x=2; 
a(x); 

} 

void d() 
{ 

int x=3; 
a(x); 

} 

void a(int x) 
{ 

switch(x) 
{ 
case 1: 
printf("b called me\n"); 
break; 
case 2: 
printf("c called me\n"); 
break; 
case 3: 
printf("d called me\n"); 
} 

} 
+0

È una "soluzione alternativa", non una soluzione. Se devi fornire API esterne, la tua via diretta sarà inutile. –

+0

@DmitrySazonov Ho risposto a ciò che il poster ha chiesto. Non più, non meno. È una soluzione. –

+2

Non è una soluzione, perché la firma della funzione è stata modificata. Non importa, è solo una mia opinione;) –

9

Prova questo:

void a(<all param declarations to a()>); 

#ifdef DEBUG 
# define a(<all params to a()>) a_debug(<all params a()>, __FUNCTION__) 
void a_debug(<all params to a()>, const char * calledby); 
#endif 

void b(void) 
{ 
    a(<all values to a()>); 
} 

#ifdef DEBUG 
# undef a 
#endif 

void a(<all param declarations to a()>) 
{ 
    printf("'%s' called\n", __FUNCTION__); 
} 

#ifdef DEBUG 
void a_debug(<all param declarations to a()>, const char * calledby) 
{ 
    printf("'%s' calledby '%s'", __FUNCTION__, calledby); 
    a(<all params to a()>); 
} 
#endif 

Se per esempio <all param declarations to a()> è int i, double d, void * p poi <all params to a()> è i, d, p.


Or (meno male, - >> - ma più codice modding, in quanto ogni chiamata a un() ha bisogno di essere toccato):

void a((<all params of normal a()>  
#ifdef DEBUG 
    , const char * calledby 
#endif 
); 

void a((<all params of normal a()>  
#ifdef DEBUG 
    , const char * calledby 
#endif 
) 
{ 
#ifdef DEBUG 
    printf("'%s' calledby '%s', __FUNCTION__, calledby); 
#endif 
    ... 
} 

... 

void b(void) 
{ 
    a(<all params of normal a()> 
#ifdef DEBUG 
     , __FUNC__ 
#endif 
    ); 
} 

__FUNCTION__ è accessibile GCC (almeno?), se si utilizza un compilatore C99 diverso sostituirlo con __func__.

+3

Sono solo io o questo codice è molto malvagio. –

+2

: D mi sembra malvagio ma è un bel modo per farlo. IMO –

1

se siete solo dopo aver conosciuto dove eravate a fini di registrazione/debug è possibile utilizzare una macro per evitare __func__ dando il nome della registrazione/funzione di debug, ma della funzione chiamarla.

Essere in una macro non comporterà una modifica a __func__ ma "sentirà" come l'utilizzo di una funzione.

ad es.

#define LOG(s, data...) log("%s: "s, __function__, ## data) 
+0

Sry, ma questo non risponde alla domanda dell'OP. – alk

+0

Dato che non sappiamo * perché * hanno bisogno di farlo, potrebbe. – Joe

6

Se si utilizza il sistema Linux, è possibile utilizzare la funzione backtrace().

Vedere man page per ulteriori dettagli e un esempio di codice.

0

consultare: https://www.gnu.org/software/libc/manual/html_node/Backtraces.html

Un backtrace è una lista delle chiamate di funzione che attualmente attivi in un thread. Il solito modo di ispezionare un backtrace di un programma è quello di utilizzare un debugger esterno come gdb. Tuttavia, a volte è utile per ottenere un backtrace a livello di codice da un programma, ad esempio ai fini della registrazione o della diagnostica.

Il file di intestazione execinfo.h dichiara tre funzioni che ottengono e manipola i backtrace del thread corrente.

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

#define FUNCTION_NAME (FUNZIONE) printf ("FUNZIONE =% s \ r \ n", # FUNZIONE);

int a() { 
    printf("A function call"); 
} 

int b() { 
    printf("B function call"); 
} 

int main(){ 
FUNCTION_NAME(a); 
FUNCTION_NAME(b); 
return 0; 

}

Problemi correlati