【问题标题】:implicit declaration of function 'enterChar' [-Wimplicit-function-declaration] [duplicate]函数'enterChar'的隐式声明[-Wimplicit-function-declaration] [重复]
【发布时间】:2015-12-18 15:39:10
【问题描述】:

我有两个关于我的 C 程序的问题: 1) 在main() 中,C = enterChar();N = enterNum();leftJustifiedPic(C, N);rightJustifiedPic(C, N); 的行都给了我implicit declaration of function。那有什么意思?我已经习惯了 Java,在 C 中的代码是否有点不同?

2) 在 enterChar() 方法中,我收到 conflicting types for 'enterChar' 错误,并且再次不明白它的含义以及它发生的原因。如果与问题有关,我正在研究 Eclipse (Cygwin-GCC)。

smb 能否详细介绍一下此类错误和警告?我很感激!

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

int main()
{
    printf("Welcome to the menu!");
    printf("The menu is:\n1. Enter/Change Character\n2. Enter/Change Number\n3. Print Triangle Type 1(Left Justified)\n4. Print Triangle Type 2(Right Justified)\n5. Quit");
    printf("\n");
    printf("Now enter a number from the menu from 1 through 5: \n");
    int num = 0;
    scanf("%d", &num);

    char C;
    int N = 0;
    switch(num){
        case 1:
            C = enterChar();
            break;
        case 2:
            N = enterNum();
            break;
        case 3:
            leftJustifiedPic(C, N);
            break;
        case 4:
            rightJustifiedPic(C, N);
            break;
        default:
            printf("Smth is wrong!");
    }

    return 0;
}

char enterChar(){
   printf("Enter your input as a character. Only 'C' and 'c' are allowed!\n");
   char input = 0 ;
   scanf("%c", &input);
   while(input != 'c' || input != 'C'){

       if(input != 'C' || input != 'c'){
            printf("You have to enter 'C' or 'c'. Try again!");
       }

   }
   return input;
}

【问题讨论】:

    标签: c


    【解决方案1】:

    1) 在使用函数之前您没有声明函数,并且您使用的 C 方言具有“隐式函数声明”。这意味着函数被隐式声明为返回 int 并接受任意数量的任意类型的参数。

    2) 因为你有一个隐式函数声明 int enterChar(),它与定义 char enterChar() 冲突。

    解决办法是在main()之前提供函数声明

    char enterChar(); // and other function declarations
    
    int main(void) {
      ....
    }
    
    // function definitions
    char enterChar() { .... }
    

    根据您的用例,使用更新版本的 C 可能值得研究,它没有这些隐式函数声明(例如 C99 或 C11)

    【讨论】:

    • main 之前的方法声明?还是在 main 之前声明变量?
    • @John 我说的是函数的声明,它们在使用之前尚未声明。
    • 感谢@juanchopanza 的回复!还有一个问题:在 C 中,我必须先声明一个函数,然后再在另一个函数中调用它吗?
    • @John 从 c99 开始,你可以。在此之前,您可以使用隐式声明,但您必须确保定义与隐式声明兼容。使用错误类型的参数调用函数可能会导致未定义的行为。
    【解决方案2】:

    当未声明函数原型时,编译器假定返回类型为int

    这就是所谓的隐式声明。

    然后,你去声明enterChar,它返回一个char。由于编译器在main 中调用它时使用了隐式声明,因此它会抱怨类型冲突。

    您可以通过在 main 中使用函数之前提供函数的显式声明来解决该问题。

    char enterChar();
    

    在使用所有函数之前提供明确的声明是一种很好的做法。

    【讨论】:

      【解决方案3】:

      函数在被调用之前必须至少声明;如果可能,它们应该在被调用之前被定义

      当函数在调用它们的同一源文件中定义时,将函数的定义移到调用者之前,如下所示:

      char enterChar( void )  // void indicates function takes no arguments
      {
          // body of enterChar
      }
      
      int enterNum( void )
      {
        // body of enterNum
      }
      
      int main( void )
      {
        ...
        c = enterChar();
        ...
        N = enterNum();
        ...
      }
      

      是的,这会使代码“向后”阅读,但它消除了一些令人头疼的问题。

      当函数在调用它们的不同源文件中定义时,请确保您有该函数的声明(使用prototype syntax!)通话前。声明可能出现在文件范围内(在任何函数之外),或者在进行调用的函数内:

      // enterChar and enterNum are *defined* in a different source file
      
      int enterNum( void ); // declaration at file scope, valid for remainder
                            // of file
      
      int main( void )
      {
        char enterChar( void ); // declaration within a block, only valid for
                                // duration of current block
        ...
        c = enterChar();  
        ...
      }
      

      在上述情况下,enterNum 的声明对整个文件有效,而enterChar 的声明仅在main 的正文内有效;如果同一源文件中的任何其他函数想要调用enterChar,它还必须在调用之前有一个声明。无论哪种方式,声明必须在调用之前。

      处理在不同源文件中定义的函数声明的通常做法是创建一个头文件,其中包含函数声明(不是定义!)并包含它定义调用函数的文件中的标头:

      /**
       * main.c
       */
      #include <stdio.h>
      #include "utils.h" // contains declarations for enterChar and enterNum
      
      int main( void )
      {
         ...
         c = enterChar();
         ...
         N = enterNum();
      }
      

      头文件:

      /**
       * utils.h
       */
      #ifndef UTILS_H    // Include guard; prevents header file from being processed
      #define UTILS_H    // more than once per translation unit
      
      char enterChar( void ); // void in the argument list indicates the function takes no arguments
      int  enterNum( void );  // an empty argument list in a declaration specifies that
                              // the function takes an *unspecified* number of arguments
                              // which is not the same thing, and not necessarily safe
      
      #endif
      

      实现文件:

      /**
       * utils.c
       */
      #include <stdio.h>
      #include <stdlib.h>
      
      #include "utils.h" // including our own header to make sure our declarations
                         // and definitions line up.
      
      char enterChar( void )
      {
        // body of enterChar
      }
      
      int enterNum( void )
      {
        // body of enterNum
      }
      

      您会注意到utils.c 包括utils.h。这是为了确保我们的声明和定义是同步的。

      【讨论】:

      • "函数必须至少在被调用之前声明 -- 是的。"如果可能,它们应该在被调用之前被定义" -- 为什么?
      • 谢谢!我试过你的方法,现在它说:expected expression before 'void'C = enterChar();N = enterNum(); 行中。你能解释一下为什么会这样吗?
      • @KeithThompson:尽量减少混乱的可能性。由于声明和定义是一回事,因此您可以避免更新一个而忘记更新另一个的问题。但是,这只适用于定义与调用者位于同一文件中的情况。
      • @John:当你说“我的方式”时,你的意思是你移动了main之前的函数定义吗?
      • 我已经在 main() 之前声明了所有方法并得到了这些错误。
      【解决方案4】:

      您对未声明的函数有“前向引用”。他们需要一个函数原型,或者在被调用之前实现。在不知道函数接受或返回什么的情况下,编译器假定 int 类型,尽管我怀疑某些编译器无论如何都会标记错误。

      您只发布了一个功能,所以我的示例仅限于此。

      #include <stdio.h>
      #include <string.h>
      
      char enterChar();           // function prototype
      
      int main(void)
      {
          char C;
          //...
          C = enterChar();       // function call
          //...
          return 0;
      }
      
      char enterChar()           // function implementation
      {
          char input = 0;
          //...
          return input;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-23
        • 1970-01-01
        • 1970-01-01
        • 2019-10-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多