1. 问题
linux下编译工程代码,编译失败,提示:
In function 'func_a':
invalid storage class for function 'func_b'
error: expected declaration or statement at end of input
2. 为什么
搜索invalid storage class
,找了几个博客,原因都是花括号没有结尾。
这个博客给出了大致的定位方式:
至于如何在linux下统计文件的{和}个数
则可以使用cat 文件名 |grep -o ‘{’|wc -l
grep的-o选项可以把一行多次出现的都统计
3. 定位
使用上述命令统计括号出现的次数,未发现括号不匹配的位置。
还是使用笨办法,把编译出问题的文件用二分的方法依次注释文件中的函数。最后定位到一个函数中。
该函数调用了一个打印宏:
#define PRINTF(fmt, args...) \
do { \
//printf(fmt, ##args); \
printf(fmt, ##args); \
} while (0)
这串代码在 si4中看来是这样的:
看上去没有任何问题= =。
然而,这串代码在vim里是这样的:
显然这个宏的定义展开后少了又花括号。
写了段测试代码(hello.c):
#include "stdlib.h"
#include "stdio.h"
#define PRINTF(fmt, args...) \
do { \
//printf(fmt, ##args); \
printf(fmt, ##args); \
} while (0)
static int
int_add_2(int a, int b)
{
return a + b;
}
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < 10; i++) {
PRINTF("i = %d\n", i);
}
}
static int
int_sub_2(int a, int b)
{
return a - b;
}
编译
gcc hello.c
编译出错
[root@wzs ~]$ gcc hello.c
hello.c: In function ‘main’:
hello.c:23:1: error: expected ‘while’ before ‘}’ token
}
^
hello.c:26:1: error: invalid storage class for function ‘int_sub_2’
int_sub_2(int a, int b)
^~~~~~~~~
hello.c:29:1: error: expected declaration or statement at end of input
}
^
hello.c:29:1: error: expected declaration or statement at end of input
4. 小结
写多行宏定义,中间不能用//
进行注释。
5. 附录
5.1 预处理
看到上述vim的显示,应该很清楚这个文件预处理后是怎样的。
使用gcc -E hello.c -o hello.i
生成预编译结果:
static int
int_add_2(int a, int b)
{
return a + b;
}
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < 10; i++) {
do {;
}
}
static int
int_sub_2(int a, int b)
{
return a - b;
}
5.2 one more thing
不能用//
进行注释,用/* */
形式的注释呢?
修改定义部分如下:
#define PRINTF(fmt, args...) \
do { \
/* printf(fmt, ##args);*/ \
printf(fmt, ##args); \
} while (0)
使用gcc -E hello.c -o hello.j
生成预编译结果:
...(省略)
static int
int_add_2(int a, int b)
{
return a + b;
}
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < 10; i++) {
do { printf("i = %d\n", i); } while (0);
}
}
static int
int_sub_2(int a, int b)
{
return a - b;
}
5.3 新的错误
修改成以下形式:
#define PRINTF(fmt, args...) \
do { \
/* printf(fmt, ##args); \ */
printf(fmt, ##args); \
} while (0)
vim显示:
显然这已经不是一个宏定义内部了,特别是最后两行。
正常是这样的
编译
hello.c:7:21: error: stray ‘##’ in program
printf(fmt, ##args); \
^~
hello.c:7:9: warning: data definition has no type or storage class
printf(fmt, ##args); \
^~~~~~
hello.c:7:9: warning: type defaults to ‘int’ in declaration of ‘printf’ [-Wimplicit-int]
hello.c:7:9: warning: parameter names (without types) in function declaration
hello.c:7:9: error: conflicting types for ‘printf’
hello.c:7:9: note: a parameter list with an ellipsis can’t match an empty parameter name list declaration
In file included from hello.c:2:0:
/usr/include/stdio.h:362:12: note: previous declaration of ‘printf’ was here
extern int printf (const char *__restrict __format, ...);
^~~~~~
hello.c:8:5: error: expected identifier or ‘(’ before ‘}’ token
} while (0)
^
hello.c:8:7: error: expected identifier or ‘(’ before ‘while’
} while (0)
^~~~~
hello.c: In function ‘main’:
hello.c:23:1: error: expected ‘while’ before ‘}’ token
}
^
hello.c:26:1: error: invalid storage class for function ‘int_sub_2’
int_sub_2(int a, int b)
^~~~~~~~~
hello.c:29:1: error: expected declaration or statement at end of input
}
^
hello.c:29:1: error: expected declaration or statement at end of input