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
Logo

更多推荐