2013-04-19 35 views
16

Trong ngôn ngữ C, __FUNCTION__ có thể được sử dụng để nhận tên hiện tại của hàm. Nhưng nếu tôi định nghĩa một hàm có tên a() và nó được gọi trong b(), như dưới đây:Làm thế nào chúng ta có thể biết tên của hàm người gọi?

b() 
{ 
    a(); 
} 

Bây giờ, trong mã nguồn, có rất nhiều chức năng như b() mà gọi một (), ví dụ c(), d(), e() ...

Có thể, trong một(), để thêm một số mã để phát hiện tên của hàm được gọi là() không?

Hơn nữa:

  1. Xin lỗi vì lỗi đánh máy sai lệch. Tôi đã sửa chữa nó.
  2. Tôi đang cố gắng tìm ra hàm nào gọi a() cho mục đích gỡ lỗi. Tôi không biết bạn làm thế nào khi ở trong cùng một tình huống?
  3. Và mã của tôi là dưới vxWorks, nhưng tôi không chắc chắn rằng nó có liên quan đến C99 hoặc điều gì đó khác.
+0

Không chắc. Nhưng [this] (http://stackoverflow.com/questions/2154852/get-a-pointer-to-the-current-function-in-c-gcc) có thể hữu ích cho bạn –

+0

Tại sao bạn muốn làm điều này? Là nó cho mục đích gỡ lỗi? – fstamour

+0

Nếu điều này chỉ để gỡ lỗi, bạn có thể xác định một macro, theo cách đó bằng cách sử dụng '__func__' sẽ trả về b, như bạn muốn. – Joe

Trả lời

33

Không có gì bạn chỉ có thể thực hiện trong a.

Tuy nhiên, với một mẹo macro đơn giản, bạn có thể đạt được những gì bạn muốn, IIUC hiển thị tên của người gọi.

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

Tôi đã phải khai báo biến caller_name như 'const char * caller_name', nhưng nó đã làm việc! – redcurry

+0

Độ chính xác: '__func__' là một phần của tiêu chuẩn C99, [...]' __FUNCTION__' là một tên khác cho '__func__', được cung cấp cho khả năng tương thích ngược với các phiên bản cũ của GCC. (nguồn: https://gcc.gnu.org/onlinedocs/gcc/Function-Names.html) –

0

Bạn có thể thẻ mỗi chức năng mà các cuộc gọi một() với một định danh số nguyên được truyền cho một() như một tham số và sau đó sử dụng một tắc hợp cụ thể xây dựng trong một() để cho các chức năng đã gọi một() .A printf() sẽ nói cho mà chức năng gọi một() tùy thuộc vào giá trị nhận dạng số nguyên nếu bạn sử dụng như một tham số để một switch-trường hợp xây dựng trong một()

#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

Đó là một "cách giải quyết", không phải là giải pháp. Nếu bạn cần cung cấp API bên ngoài - cách trực tiếp của bạn sẽ vô ích. –

+0

@DmitrySazonov Tôi đã trả lời những gì các poster yêu cầu.Ngoài ra, không ít hơn. Nó là một giải pháp. –

+2

Nó không phải là một giải pháp, bởi vì bạn đã thay đổi chữ ký chức năng. Nevermind, nó chỉ là ý kiến ​​của tôi;) –

9

Hãy thử điều này:

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 

Nếu ví dụ <all param declarations to a()>int i, double d, void * p sau đó <all params to a()>i, d, p.


Hoặc (ít ác; - >> - nhưng mã modding hơn, vì mỗi cuộc gọi đến một() cần phải được xúc động):

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__ có sẵn trên GCC (ít nhất?), nếu sử dụng trình biên dịch C99 khác, hãy thay thế bằng __func__.

+3

Chỉ là tôi hay là mã này rất độc ác. –

+2

: D nó trông xấu với tôi nhưng nó là một cách mát mẻ để làm điều đó IMO –

1

Nếu bạn chỉ sau khi biết nơi bạn đã cho các mục đích khai thác gỗ/debug bạn có thể sử dụng một macro để tránh __func__ cho tên đăng nhập/chức năng debug của bạn nhưng của hàm gọi nó.

Đang ở trong macro sẽ không dẫn đến thay đổi đối với __func__ nhưng sẽ "cảm thấy" như sử dụng chức năng.

ví dụ:

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

Sry, nhưng điều này không trả lời câu hỏi của OP. – alk

+0

Vì chúng tôi không biết * tại sao * họ cần phải làm điều này, nó có thể. – Joe

6

Nếu bạn đang sử dụng hệ thống Linux, bạn có thể sử dụng chức năng backtrace().

Xem man page để biết thêm chi tiết và ví dụ về mã.

0

Tham khảo: https://www.gnu.org/software/libc/manual/html_node/Backtraces.html

Một backtrace là một danh sách các chức năng cuộc gọi có hiện hoạt động trong một thread. Cách thông thường để kiểm tra một backtrace của một chương trình là sử dụng một trình gỡ rối bên ngoài như gdb. Tuy nhiên, đôi khi nó hữu ích để có được một backtrace lập trình từ bên trong một chương trình, ví dụ: cho mục đích ghi nhật ký hoặc chẩn đoán.

Tệp tiêu đề execinfo.h khai báo ba hàm nhận được và thao tác backtraces của chuỗi hiện tại.

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

#define FUNCTION_NAME cho (CHỨC NĂNG) printf ("CHỨC NĂNG =% s \ r \ n", # CHỨC NĂNG);

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

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

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

}

Các vấn đề liên quan