【问题标题】:Error while making conditional compilation进行条件编译时出错
【发布时间】:2020-12-07 06:04:42
【问题描述】:

[在此处输入链接描述][1]我正在编写这个程序,它将启用条件编译。

当程序以这样的标准方式编译时,它可以正常工作而没有任何错误消息:

gcc -Werror -Wall -pedantic -ansi -g -c display.c -o displayStack 

但是当我想使用条件编译进行编译时,我收到一条错误消息,提示我的函数在 display.c 中有隐式声明

我是这样编译的:

gcc -Werror -Wall -pedantic -ansi -g -c display.c -o displayStack -D STACK

这是我在代码中编写条件命令的方式:

#ifdef STACK
printLinkedList( stack );
#endif

这里是 stack.h 文件,其中包含 LinkedList.h 的包含,它具有 printLinkedList 的函数原型。

#ifndef STACK
#define STACK

#include "LinkedList.h"

LinkedList *createStack();
void push( LinkedList *, void * );
void *top( LinkedList * );
void *pop( LinkedList * );
void freeStack( LinkedList * );

#endif

请问这里有什么问题吗?我似乎找不到问题,因为第一条语句运行良好,但是当我添加“-D STACK”时,程序只显示错误消息。我的编译命令有问题吗?

我收到的错误消息:

display.c: In function ‘display’:
display.c:21:5: error: unknown type name ‘LinkedList’
   21 |     LinkedList *stack = NULL;
      |     ^~~~~~~~~~
display.c:22:13: error: implicit declaration of function ‘createStack’ [-Werror=implicit-function-declaration]
   22 |     stack = createStack();
      |             ^~~~~~~~~~~
display.c:22:11: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   22 |     stack = createStack();
      |           ^
display.c:47:21: error: implicit declaration of function ‘push’ [-Werror=implicit-function-declaration]
   47 |                     push( stack, bracket );
      |                     ^~~~
display.c:52:30: error: request for member ‘head’ in something not a structure or union
   52 |                     if( stack->head != NULL )
      |                              ^~
display.c:54:38: error: implicit declaration of function ‘top’ [-Werror=implicit-function-declaration]
   54 |                         popBracket = top( stack );
      |                                      ^~~
display.c:54:36: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   54 |                         popBracket = top( stack );
      |                                    ^
display.c:72:42: error: implicit declaration of function ‘pop’ [-Werror=implicit-function-declaration]
   72 |                             popBracket = pop( stack );
      |                                          ^~~
display.c:72:40: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   72 |                             popBracket = pop( stack );
      |                                        ^
display.c:108:17: error: implicit declaration of function ‘printLinkedList’ [-Werror=implicit-function-declaration]
  108 |                 printLinkedList( stack );
      |                 ^~~~~~~~~~~~~~~
display.c:147:22: error: request for member ‘head’ in something not a structure or union
  147 |             if( stack->head == NULL )   /* Good case */
      |                      ^~
display.c:151:28: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
  151 |                 popBracket = top( stack );
      |                            ^
display.c:164:5: error: implicit declaration of function ‘freeStack’ [-Werror=implicit-function-declaration]
  164 |     freeStack( stack );
      |     ^~~~~~~~~
cc1: all warnings being treated as errors
calmen@calmen:~/Desktop/Project/BracketCheck$ vim display.h
calmen@calmen:~/Desktop/Project/BracketCheck$ gcc -Werror -Wall -pedantic -ansi -g -c display.c -o displayStack -D STACK
display.c: In function ‘display’:
display.c:21:5: error: unknown type name ‘LinkedList’
   21 |     LinkedList *stack = NULL;
      |     ^~~~~~~~~~
display.c:22:13: error: implicit declaration of function ‘createStack’ [-Werror=implicit-function-declaration]
   22 |     stack = createStack();
      |             ^~~~~~~~~~~
display.c:22:11: error: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   22 |     stack = createStack();
      |           ^
display.c:47:21: error: implicit declaration of function ‘push’ [-Werror=implicit-function-declaration]
   47 |                     push( stack, bracket );
      |                     ^~~~
display.c:52:30: error: request for member ‘head’ in something not a structure or union
   52 |                     if( stack->head != NULL )
      |                              ^~
display.c:54:38: error: implicit declaration of function ‘top’ [-Werror=implicit-function-declaration]
   54 |                         popBracket = top( stack );
      |                                      ^~~
display.c:54:36: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   54 |                         popBracket = top( stack );
      |                                    ^
display.c:72:42: error: implicit declaration of function ‘pop’ [-Werror=implicit-function-declaration]
   72 |                             popBracket = pop( stack );
      |                                          ^~~
display.c:72:40: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
   72 |                             popBracket = pop( stack );
      |                                        ^
display.c:108:17: error: implicit declaration of function ‘printLinkedList’ [-Werror=implicit-function-declaration]
  108 |                 printLinkedList( stack );
      |                 ^~~~~~~~~~~~~~~
display.c:147:22: error: request for member ‘head’ in something not a structure or union
  147 |             if( stack->head == NULL )   /* Good case */
      |                      ^~
display.c:151:28: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
  151 |                 popBracket = top( stack );
      |                            ^
display.c:164:5: error: implicit declaration of function ‘freeStack’ [-Werror=implicit-function-declaration]
  164 |     freeStack( stack );
      |     ^~~~~~~~~
cc1: all warnings being treated as errors

可以在此处的文件夹中找到这些文件。 [1]:https://github.com/Calmen00-code/BracketCheck

【问题讨论】:

  • 我们只能猜测而没有看到您应该提供的complete minimal verifiable example。并提供exact错误信息。但听起来在代码中调用它的点之前没有printLinkedList函数的定义或原型。
  • 它与条件编译本身没有任何关系。这只是意味着您通过添加-DSTACK 启用的代码中存在错误。如果没有-DSTACK,代码将被忽略,因此编译器看不到其中的任何错误。您没有显示实际的错误消息(在寻求帮助时您应该始终剪切/粘贴实际的错误消息),但很可能它说printLinkedList 是问题所在。在 Google 上搜索错误“隐式声明”的含义以及如何解决。
  • 代码需要作为可验证的最小示例出现在问题中,而不是作为外部链接。无论如何,我认为我们已经相当清楚地表明了可能的错误是什么。你明白上面所说的吗 - 函数需要在调用之前声明。
  • 嗨,我在问题中包含了 github 链接。我不知道为什么会发生隐式声明,因为我已经添加了我的函数声明,并且当我在没有条件编译的情况下编译它时它可以正常工作而不会显示错误消息。希望我已经把问题说清楚了..提前谢谢!
  • 谢谢@kaylum。是的,我知道函数原型设计必须在函数定义之前。我已经这样做了,但它似乎仍然显示错误消息。

标签: c conditional-compilation makefile


【解决方案1】:

问题在于stack.h 文件中的包含保护:

#ifndef STACK

当您随后在命令行上定义STACK 时,条件变为 FALSE,并且不包括标题内容。这会导致 C 文件中缺少原型。

要解决此问题,您需要更改 C 文件或头文件以使用不同的预处理器变量。

【讨论】:

  • 是的,我已经在 stack.h 中使用了包含的 STACK。将其更改为其他类似 STACK_H 将解决问题。谢谢!
【解决方案2】:

gcc -Werror -Wall -pedantic -ansi -g -c display.c -o displayStack -D STACK

很奇怪。我会删除-DSTACK 之间的空格

您可能有兴趣将-Wextra -fanalyze 添加到您的gcc 命令中。阅读关于 invoking GCC 的章节,关于 static analyzer options 的章节,并在 2020 年底考虑升级到 GCC 10

另外,-ansi 指的是旧的 C 标准。阅读n1570Modern C 然后考虑使用-std=c11

使用make CFLAGS='-Wall -Wextra -g -std=c11' 编译代码BracketCheck.tar.gz(md5sum 1b81b34f26db85fef69bda62a5bd4e63)时,我得到:

 display.c: In function ‘display’:
 display.c:21:5: error: unknown type name ‘LinkedList’
    21 |     LinkedList *stack = NULL;
       |     ^~~~~~~~~~
 display.c:22:13: warning: implicit declaration of function ‘createStack’ [-Wimplicit-function-declaration]
    22 |     stack = createStack();
       |             ^~~~~~~~~~~
 display.c:22:11: warning: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
    22 |     stack = createStack();
       |           ^
 display.c:47:21: warning: implicit declaration of function ‘push’ [-Wimplicit-function-declaration]
    47 |                     push( stack, bracket );
       |                     ^~~~
 display.c:52:30: error: request for member ‘head’ in something not a structure or union
    52 |                     if( stack->head != NULL )
       |                              ^~
 display.c:54:38: warning: implicit declaration of function ‘top’ [-Wimplicit-function-declaration]
    54 |                         popBracket = top( stack );
       |                                      ^~~
 display.c:54:36: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
    54 |                         popBracket = top( stack );
       |                                    ^
 display.c:72:42: warning: implicit declaration of function ‘pop’ [-Wimplicit-function-declaration]
    72 |                             popBracket = pop( stack );
       |                                          ^~~
 display.c:72:40: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
    72 |                             popBracket = pop( stack );
       |                                        ^
 display.c:108:17: warning: implicit declaration of function ‘printLinkedList’ [-Wimplicit-function-declaration]
   108 |                 printLinkedList( stack );
       |                 ^~~~~~~~~~~~~~~
 display.c:147:22: error: request for member ‘head’ in something not a structure or union
   147 |             if( stack->head == NULL )   /* Good case */
       |                      ^~
 display.c:151:28: warning: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
   151 |                 popBracket = top( stack );
       |                            ^
 display.c:164:5: warning: implicit declaration of function ‘freeStack’ [-Wimplicit-function-declaration]
   164 |     freeStack( stack );

这是在 Linux/x86-64/Ubuntu 20.04 上使用GCC 10.2

我建议您修复您的代码,直到您完全没有收到任何警告为止。

添加-DSTACK 并不能修复所有错误。一旦它们都固定使用GDB 来了解您的程序的行为。

您可能会对this draft 报告以及资助它的DECODERCHARIOT 项目感兴趣。

您也可以尝试在您的代码上使用Frama-CClang static analyzer。请注意Rice's theorem

您可以考虑使用GNU autoconf 和/或GNU bison 和/或ANTLR 和/或GPP 使用@987654338 生成您的一些代码(在C 中,或您的makefile ...) @技巧看完了Dragon book

【讨论】:

  • -D 选项接受一个参数,该参数可以从标志附加或分离。同上 -l-L-I(和 -U 和……)。当然,在选项和参数之间放置一个空格是一种惯例,但这样做是有效的。有趣的是,GCC 不接受-Wvla 之间的空格(或-fanalyze 之间的空格)——因此可能也不接受其他一些选项。所以留出空间当然更简单也更正常。
猜你喜欢
  • 2019-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多