簡體   English   中英

C。 錯誤:重復的 function 定義。 這可能是什么原因?

[英]C. Error: Duplicated function definition. What could be cause of this?

我是一名初學者程序員,我正在使用 C 語言並使用 SDL2 庫編寫游戲“Snake”的簡單實現。 一切都很順利,直到我決定將代碼分成單獨的文件和函數。 現在,當我嘗試編譯我的項目時出現錯誤:

Snake/src\snake.c:8: duplicated definition «init_snake»; CMakeFiles\Snake.dir/objects.a(main.c.obj):Snake/src\..\src\snake.c:8: first definition

我很困惑 function 的第一個定義及其重新定義位於單個文件的同一行。 我用 IDE 搜索了整個項目,發現只有兩個地方出現了 function “init_snake”。 事實上,這就是她的定義和電話的位置。 在我的谷歌搜索之后,我發現我在 header 文件中初始化變量時出錯的信息。 像這樣:

const static int SIZE = 10;

為了感興趣,我從 header 文件中刪除了變量,並決定不使用它們進行測試(盡管我覺得這無濟於事,因為錯誤是 function,而不是變量)。 它真的沒有幫助。

可以肯定的是,我決定搜索有關包含的信息。 為了避免代碼交叉,我添加了 #include guard(在 Internet 上找到)和#pragma once 雖然它對這個錯誤沒有幫助,但它很酷(如果我正確理解它是如何工作的)。

所以特地來這里請教專家。 這是怎么回事? 因為我在一個地方定義了一個 function,然后我從另一個地方調用它一次。

下面我應用當前版本的代碼。

main.c

#include "../include/main.h"

#include "../src/snake.c"

int
main(int argc,
     char *args[])
{
    SDL_Window *window = NULL;
    window = SDL_CreateWindow("Snake",
                              SDL_WINDOWPOS_CENTERED,
                              SDL_WINDOWPOS_CENTERED,
                              525,
                              525,
                              SDL_WINDOW_SHOWN);
    if (NULL == window)
    {
        printf("Window was not created. Error: %s\n", SDL_GetError());
        exit(1);
    }

    SDL_Renderer *renderer = NULL;
    renderer = SDL_CreateRenderer(window,
                                  -1,
                                  SDL_RENDERER_ACCELERATED);
    if (NULL == renderer)
    {
        printf("Renderer was not created. Error: %s\n", SDL_GetError());
        exit(1);
    }

    SDL_SetRenderDrawColor(renderer, 0x0, 0x0, 0x0, 0xFF);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);

    init_snake(renderer, 525 / 2, 525 / 2, 16);

    bool quit = false;
    SDL_Event e;
    while (!quit)
    {
        //Handle events on queue
        while (SDL_PollEvent(&e) != 0)
        {
            if (e.type == SDL_QUIT)
            {
                quit = true;
            }
        }
    }

    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    SDL_Quit();

    return 0;
}

主文件

#pragma once
#ifndef MAIN_H
#define MAIN_H

#include "SDL2/SDL.h"

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

#endif

蛇.c

#include "../include/snake.h"

void
init_snake(SDL_Renderer *renderer,
           int x,
           int y,
           int length)
{
    assert(renderer);

    for (int i = 0; i < length; i++)
    {
        SDL_Rect rect;
        rect.x = x;
        rect.y = y;
        rect.w = 12;
        rect.h = 10;
        SDL_SetRenderDrawColor(renderer, 0x0, 0xFF, 0x0, 0xFF);
        SDL_RenderFillRect(renderer, &rect);
        SDL_RenderPresent(renderer);
    }
}

蛇.h

#pragma once
#ifndef SNAKE_H
#define SNAKE_H
    
#include "SDL2/SDL.h"

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

如果我在創建這個問題時做錯了什么,請告訴我 - 我會嘗試解決它。 如果您需要任何其他信息,請告訴我,我會澄清。 感謝您的時間。

C 標准或編譯器通常沒有規定您不能包含.c文件。 但是對於我們如何命名和使用文件有一個約定:

名稱以.c結尾的文件包含對象和/或函數的定義 對於對象,定義是編寫的聲明,以便它們導致存儲被保留(例如具有初始化的外部定義,例如int MyFoo = 0; ,盡管這些天我們通常避免外部可見的對象)。 對於函數,定義是包含 function(它執行的代碼)主體的聲明。

名稱以.h結尾的文件包含不是定義的對象和/或函數的聲明 這些聲明僅描述了 object 或 function 沒有定義它。 對於對象, extern int MyFoo; 是一個描述但不定義MyFoo的聲明。 對於 function extern int bar(double x); 是一個沒有定義bar的聲明。 extern是 function 的默認值,因此您可以將其關閉並寫入int bar(double x); .

給定一個文件名,例如MyModuleX ,我們通常使用文件MyModuleX.c來定義MyModuleX的對象和函數,我們使用文件MyModuleX.h來告訴程序的其他部分MyModuleX提供的對象和函數。

所以每個使用MyModuleX的源文件都應該有#include "MyModuleX.h" 此外, MyModuleX.c也應該有,所以編譯器會同時看到聲明和定義,並可以檢查它們是否匹配。 沒有文件應該有#include "MyModuleX.c" ,因為我們不會通過包含源文件將函數放入程序中。 相反,我們分別編譯每個源文件(可能在一個命令中,但編譯器將單獨編譯它們)並將它們鏈接在一起。

如果你包含snake.c ,這意味着它的代碼在編譯時會被包含兩次。 在文件上使用#include只是將所有代碼插入文件中。 意思是,當編譯發生時, main.c包含所有snake.c ,並且由於您也在編譯snake.c將定義兩次。 因此,您必須在main.c snake.c 只需包含其 header 文件即可。 在 header 文件中,預定義您想在其他地方使用的任何功能,因此您不必包含整個 C 文件即可訪問這些功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM