user-0 提问: 请问一个__FUNCTION__的问题？

回复:
user: user-1
content: 纯粹的宏操作是不行的了，得自己写函数，然后用宏封装函数。

user: user-0
content: 引用 21 楼 ForestDB 的回复: $ cat main.c  int main() {     puts(__FUNCTION__);     puts(__func__);     puts(__FILE__); }  $ cpp main.c  # 1 "main.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "main.c" int main() {     puts(__FUNCTION__);     puts(__func__);     puts("main.c"); }  $ gcc -S main.c  main.c: In function ‘main’: main.c:3:5: warning: implicit declaration of function ‘puts’ [-Wimplicit-function-declaration]      puts(__FUNCTION__);      ^ $ cat main.s 	.file	"main.c" 	.section	.rodata .LC0: 	.string	"main.c" 	.text 	.globl	main 	.type	main, @function main: .LFB0: 	.cfi_startproc 	pushq	%rbp 	.cfi_def_cfa_offset 16 	.cfi_offset 6, -16 	movq	%rsp, %rbp 	.cfi_def_cfa_register 6 	movl	$__FUNCTION__.1832, %edi 	call	puts 	movl	$__func__.1833, %edi 	call	puts 	movl	$.LC0, %edi 	call	puts 	movl	$0, %eax 	popq	%rbp 	.cfi_def_cfa 7, 8 	ret 	.cfi_endproc .LFE0: 	.size	main, .-main 	.section	.rodata 	.type	__FUNCTION__.1832, @object 	.size	__FUNCTION__.1832, 5 __FUNCTION__.1832: 	.string	"main" 	.type	__func__.1833, @object 	.size	__func__.1833, 5 __func__.1833: 	.string	"main" 	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609" 	.section	.note.GNU-stack,"",@progbits  看到了么？准确的说__FILE__和__LINE__才是预定义宏，且是标准定义的；而__FUNCTION__和__func__是编译器预定义符号，是个变量，且从某种意义上来说并不是标准（__func__已经是C99的标准了）。  详见 https://gcc.gnu.org/onlinedocs/gcc-7.2.0/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Function-Names.html#Function-Names  These identifiers are variables, not preprocessor macros, and may not be used to initialize char arrays or be concatenated with string literals. 非常感谢你的的回答。那是不是说，不能将__FUNCTION__当成宏的参数传到那个宏con中去？看了你的回答，我估计确实不行。那我只能换个思路修改那个宏的写法了。

user: user-0
content: 引用 22 楼 paschen 的回复:#define con(x,y） x#y 右括号你用成中文的了，改成英文的则没问题了 这是个笔误，改了以后还是不行。

user: user-0
content: 引用 25 楼 ForestDB 的回复:纯粹的宏操作是不行的了，得自己写函数，然后用宏封装函数。 谢谢回答，我已经修改了。揭帖给分

user: user-2
content: 更何况就算楼主完美解决了__FUNCTION__相关问题，仍不能“完美”解决代码调试的问题。 参考： http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程  再参考： 请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George  前微软C#编辑器的开发主管Jay Bazuzi列出的一些有助于找到正确方向的问题；他觉得前同事们应该用这些问题来问自己；实际上不管在哪里工作的开发者们都应该经常问问自己这些问题： ◆“要保证这个问题不会再出现，我该怎么做？” ◆“要想少出些Bug，我该怎么做？” ◆“要保证Bug容易被修复，我该怎么做？” ◆“要保持对变化的快速响应，我该怎么做？” ◆“要保证我的软件的运行速度，我该怎么做？” 如果大多数团队都能不时问一下自己，必定会从中得益，因为这些都是真正强而有力的问题。

user: user-2
content: 建议楼主深入理解编译的若干步骤 及 各步骤都干了些什么 以及 编译期和运行期的区别与联系。

user: user-2
content: 代码生成技术是业界很成熟的技术。

user: user-0
content: 引用 13 楼 zhao4zhong1 的回复:实在不行，楼主只能使用代码生成技术了。 代码生成技术参考下面： //codegen.c // 输入一组字符串，比如 // aa ss ddd dd 33 dd // 然后自动生成一个函数 int A(const char*); // 实现A("aa")返回0  A("ss")返回1 依次类推 #include <stdio.h> int main(int argc,char **argv) {     int i;     if (argc<2) {         printf("%s p1 [p2 ...] [>result.c]\nGenerate code int A(const char *a); 0==A(\"p1\") 1==A(\"p2\") ...",argv[0]);         return 1;     }     //printf("#include <string.h>\n");     printf("int A(const char *a) {\n");     for (i=0;i<argc-1;i++) {         printf("    if (0==strcmp(a,\"%s\")) return %d;\n",argv[i+1],i);     }     printf("    return -1;\n");     printf("}\n");     return 0; } //C:\test\Debug>codegen.exe //codegen.exe p1 [p2 ...] [>result.c] //Generate code int A(const char *a); 0==A("p1") 1==A("p2") ... //C:\test\Debug>codegen.exe aa ss ddd dd 33 dd //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} // //c:\test\Debug>codegen.exe aa ss ddd dd 33 dd >result.c // //c:\test\Debug>type result.c //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} //  谢谢回答！请问有简单的做法吗，因为是老代码 ，我不想改的太多。

user: user-2
content: 实在不行，楼主只能使用代码生成技术了。 代码生成技术参考下面： //codegen.c // 输入一组字符串，比如 // aa ss ddd dd 33 dd // 然后自动生成一个函数 int A(const char*); // 实现A("aa")返回0  A("ss")返回1 依次类推 #include <stdio.h> int main(int argc,char **argv) {     int i;     if (argc<2) {         printf("%s p1 [p2 ...] [>result.c]\nGenerate code int A(const char *a); 0==A(\"p1\") 1==A(\"p2\") ...",argv[0]);         return 1;     }     //printf("#include <string.h>\n");     printf("int A(const char *a) {\n");     for (i=0;i<argc-1;i++) {         printf("    if (0==strcmp(a,\"%s\")) return %d;\n",argv[i+1],i);     }     printf("    return -1;\n");     printf("}\n");     return 0; } //C:\test\Debug>codegen.exe //codegen.exe p1 [p2 ...] [>result.c] //Generate code int A(const char *a); 0==A("p1") 1==A("p2") ... //C:\test\Debug>codegen.exe aa ss ddd dd 33 dd //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} // //c:\test\Debug>codegen.exe aa ss ddd dd 33 dd >result.c // //c:\test\Debug>type result.c //int A(const char *a) { //    if (0==strcmp(a,"aa")) return 0; //    if (0==strcmp(a,"ss")) return 1; //    if (0==strcmp(a,"ddd")) return 2; //    if (0==strcmp(a,"dd")) return 3; //    if (0==strcmp(a,"33")) return 4; //    if (0==strcmp(a,"dd")) return 5; //    return -1; //} //

user: user-0
content: 引用 11 楼 cfjtaishan 的回复:楼主说的宏是不是__func__呢？ 我用__func__好像也不行。

user: user-3
content: 楼主说的宏是不是__func__呢？

user: user-4
content: #define con(x,y） x#y 右括号你用成中文的了，改成英文的则没问题了

user: user-1
content: $ cat main.c  int main() {     puts(__FUNCTION__);     puts(__func__);     puts(__FILE__); }  $ cpp main.c  # 1 "main.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "main.c" int main() {     puts(__FUNCTION__);     puts(__func__);     puts("main.c"); }  $ gcc -S main.c  main.c: In function ‘main’: main.c:3:5: warning: implicit declaration of function ‘puts’ [-Wimplicit-function-declaration]      puts(__FUNCTION__);      ^ $ cat main.s 	.file	"main.c" 	.section	.rodata .LC0: 	.string	"main.c" 	.text 	.globl	main 	.type	main, @function main: .LFB0: 	.cfi_startproc 	pushq	%rbp 	.cfi_def_cfa_offset 16 	.cfi_offset 6, -16 	movq	%rsp, %rbp 	.cfi_def_cfa_register 6 	movl	$__FUNCTION__.1832, %edi 	call	puts 	movl	$__func__.1833, %edi 	call	puts 	movl	$.LC0, %edi 	call	puts 	movl	$0, %eax 	popq	%rbp 	.cfi_def_cfa 7, 8 	ret 	.cfi_endproc .LFE0: 	.size	main, .-main 	.section	.rodata 	.type	__FUNCTION__.1832, @object 	.size	__FUNCTION__.1832, 5 __FUNCTION__.1832: 	.string	"main" 	.type	__func__.1833, @object 	.size	__func__.1833, 5 __func__.1833: 	.string	"main" 	.ident	"GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609" 	.section	.note.GNU-stack,"",@progbits  看到了么？准确的说__FILE__和__LINE__才是预定义宏，且是标准定义的；而__FUNCTION__和__func__是编译器预定义符号，是个变量，且从某种意义上来说并不是标准（__func__已经是C99的标准了）。  详见 https://gcc.gnu.org/onlinedocs/gcc-7.2.0/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Function-Names.html#Function-Names  These identifiers are variables, not preprocessor macros, and may not be used to initialize char arrays or be concatenated with string literals.

user: user-0
content: 引用 19 楼 cutmelon 的回复:[quote=引用 楼主 maoaq 的回复:] 我写了一个宏 #define con(x,y） x#y  然后在main函数中写了下面的代码： char * ss = con(__FUNCTIION__,2);  用gcc编译出错。  但char * ss = con(“1”，“2”);是正确的。  请问这个宏应该怎么写才对？  我用gcc的-i选项编译，发现这个__FUNCTION__没有展开，所以编译错误，请问这个__FUNCTION__是在什么时候展开的？ 不知道你的代码文件里怎么写的，看上面红色部分，括号是全角，FUNCTION多了个I，这应该编译不过去吧 我怎么写是能跑的：#include <stdio.h>  #define con(x,y) x#y  void main() { 	char* ss=con(__FUNCTION__,2); 	printf(ss); } [/quote] 那个是笔误。 我的代码如下： #include <stdio.h>  #define con(x,y) x#y  int main(int argc, char** argv){	 	char * ss = con(__FUNCTION__,2); 	printf("ss = %s\n",ss); 	return 0; } 但是编译不过。你是用的什么编译器？我的是gcc4.4.7. 而且把__FUNCTION__换成__FILE__就可以，换成__func__也不对。

user: user-5
content: 引用 楼主 maoaq 的回复:我写了一个宏 #define con(x,y） x#y  然后在main函数中写了下面的代码： char * ss = con(__FUNCTIION__,2);  用gcc编译出错。  但char * ss = con(“1”，“2”);是正确的。  请问这个宏应该怎么写才对？  我用gcc的-i选项编译，发现这个__FUNCTION__没有展开，所以编译错误，请问这个__FUNCTION__是在什么时候展开的？ 不知道你的代码文件里怎么写的，看上面红色部分，括号是全角，FUNCTION多了个I，这应该编译不过去吧 我怎么写是能跑的：#include <stdio.h>  #define con(x,y) x#y  void main() { 	char* ss=con(__FUNCTION__,2); 	printf(ss); }

user: user-0
content: 引用 17 楼 zhao4zhong1 的回复:更何况就算楼主完美解决了__FUNCTION__相关问题，仍不能“完美”解决代码调试的问题。 参考： http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程  再参考： 请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George  前微软C#编辑器的开发主管Jay Bazuzi列出的一些有助于找到正确方向的问题；他觉得前同事们应该用这些问题来问自己；实际上不管在哪里工作的开发者们都应该经常问问自己这些问题： ◆“要保证这个问题不会再出现，我该怎么做？” ◆“要想少出些Bug，我该怎么做？” ◆“要保证Bug容易被修复，我该怎么做？” ◆“要保持对变化的快速响应，我该怎么做？” ◆“要保证我的软件的运行速度，我该怎么做？” 如果大多数团队都能不时问一下自己，必定会从中得益，因为这些都是真正强而有力的问题。 用其他的办法应该可以解决，只是这个宏是老代码中的，有好几个地方调用，如果用其他的方法，改的地方可能比较多，所以想知道有没有比较简单的办法。谢谢！

user: user-0
content: 引用 7 楼 maoaq 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 仅供参考：#include <stdio.h> #define DEBUG2(x,y) "Line " #y " of File " x #define DEBUG1(x,y) DEBUG2(x,y) #define LINE_FILE DEBUG1( __FILE__ , __LINE__ )      const char *str = LINE_FILE; void main() {     printf("%s\n",str); } //Line 10 of File c:\tmp\tmp\foo.c  这个肯定知道，为什么放到我写的那个宏里就不对了呢？[/quote] 不好意思，看错了，我试试这个，谢谢！  引用 7 楼 maoaq 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 仅供参考：#include <stdio.h> #define DEBUG2(x,y) "Line " #y " of File " x #define DEBUG1(x,y) DEBUG2(x,y) #define LINE_FILE DEBUG1( __FILE__ , __LINE__ )      const char *str = LINE_FILE; void main() {     printf("%s\n",str); } //Line 10 of File c:\tmp\tmp\foo.c  这个肯定知道，为什么放到我写的那个宏里就不对了呢？[/quote] 不好意思，看错了。我试验了你的代码，结果没有问题，但是我有以下的问题想请教一下： 1 为什么用 __FUNCTIION__修改你的代码，编译不过，与我遇到的现象一样？ 2 我现在必须要用__FUNCTIION__来作为参数调用宏，请问这样应该怎么写宏？我直接调用那个DEBUG1，编译不过。 非常感谢回答。

user: user-6
content: 请再研究研究

user: user-0
content: 引用 4 楼 wyyy2088511 的回复:http://blog.csdn.net/wyyy2088511/article/details/77162949   #是字符串，##是连接符 可是我的那个宏为什么不对呢？

user: user-0
content: 引用 5 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #define DEBUG2(x,y) "Line " #y " of File " x #define DEBUG1(x,y) DEBUG2(x,y) #define LINE_FILE DEBUG1( __FILE__ , __LINE__ )      const char *str = LINE_FILE; void main() {     printf("%s\n",str); } //Line 10 of File c:\tmp\tmp\foo.c  这个肯定知道，为什么放到我写的那个宏里就不对了呢？