Linux c codeblock的使用(二):在工程中編譯多個文件


(一)前言

我們剛開始學習linux c的時候,一般都是在一個c文件里面寫完所有程序,然后用gcc編譯這個c文件就好了,十分簡單。

但是你有沒有想過,如果我們希望將不同模塊的代碼放到不同的c文件,然后最后編譯成一個程序,這個時候又應該怎么辦呢?

有人會說,怎么用這么麻煩,直接放在一個c文件里面就好了。但是你總是要考慮一下現實情況的多變性,雖然同時編譯很多個c文件不好,但是只會編譯一個c文件顯得你很LOW。

(二)例子

具一個現實當中簡單的例子

比如說我們要編譯如下程序,程序當中有兩個c文件。以下程序都是我在之前的博客發過的,大家如果很在意代碼的意思的話,可以在之前的博客里面找一找。

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MEM_PART "/proc/meminfo"


#include "file.h"

//用於存儲內存信息的結構體
struct mem_info
{
    char MemTotal[20];
    char MemFree[20];
    char MemAvailable[20];
    char Buffers[20];
    char Cached[20];
};

typedef struct mem_info MEM_info,*pMEM_info;


//按行讀取/proc/meminfo中的信息,並保存到mem結構體中
int get_mem_info(pMEM_info mem)
{
    char buffer[300];
    if(NULL==mem)
    {
        printf("\nget_mem_info:param null!\n");
        return 0;
    }
    memset(mem,0,sizeof(MEM_info));
    if(1==get_file_line(buffer,MEM_PART,1))//讀取第一行
    {
        sscanf(buffer,"%*s %s",mem->MemTotal);
        if(1==get_file_line(buffer,MEM_PART,2))//讀取第二行
        {   sscanf(buffer,"%*s %s",mem->MemFree);
            if(1==get_file_line(buffer,MEM_PART,3))//讀取第三行
            {   sscanf(buffer,"%*s %s",mem->MemAvailable);
                if(1==get_file_line(buffer,MEM_PART,4))//讀取第四行
                    {   sscanf(buffer,"%*s %s",mem->Buffers);
                        if(1==get_file_line(buffer,MEM_PART,5))//讀取第五行
                            {
                                sscanf(buffer,"%*s %s",mem->Cached);
                                return 1;
                            }

                    }

            }

        }

    }

    return 0;
}

int main()
{
    char result[3000];
    char result2[100];
    MEM_info mem;

    get_file_line(result,MEM_PART,1);

    sscanf(result,"%*s %s",result2);
    printf("\n%s\n",result);
    printf("\n%s\n",result2);

    get_mem_info(&mem);
    printf("\n%s %s %s %s %s\n",mem.MemTotal,mem.MemFree,mem.MemAvailable,mem.Buffers,mem.Cached);

    

    printf("\n%s\n",result);


    return 1;

}

file.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <fcntl.h>
#define FILEBUFFER_LENGTH 5000
#define EMPTY_STR ""
//打開fileName指定的文件,從中讀取第lineNumber行
//返回值:成功返回1,失敗返回0
int get_file_line(char *result,char *fileName,int lineNumber)
{
    FILE *filePointer;
    int i=0;
    char buffer[FILEBUFFER_LENGTH];
    char *temp;

    memset(buffer,'\0',FILEBUFFER_LENGTH*sizeof(char));
    strcpy(buffer,EMPTY_STR);

    if((fileName==NULL)||(result==NULL))
    {
        return 0;
    }

    if(!(filePointer=fopen(fileName,"rb")))
    {return 0;}


    while((!feof(filePointer))&&(i<lineNumber))
    {
        if(!fgets(buffer,FILEBUFFER_LENGTH,filePointer))
        {
            return 0;
        }
        i++;//差點又忘記加這一句了
    }

   /* printf("\n%d\n",sizeof(*result));
    if(strlen(buffer)>sizeof(*result))//不能夠這么寫,雖然fgets讀取一行后會在末尾加上'\0',但是sizeof(result)得到的結果卻是result本身類型的大小,所以不能夠這么算。當靜態數組傳入函數時,在函數內部只能知道它是一個指針
    {
        return 0;
    }*/




    if(0!=fclose(filePointer))
    {
        return 0;
    }

    if(0!=strcmp(buffer,EMPTY_STR))
    {
        while(NULL!=(temp=strstr(buffer,"\n")))
        {
            *temp='\0';
        }

        while(NULL!=(temp=strstr(buffer,"\r")))
        {
            *temp='\0';
        }


        strcpy(result,buffer);
    }else
    {
        strcpy(result,EMPTY_STR);
        return 0;
    }

    return 1;
}

file.h

#ifndef FILE_H_INCLUDED
#define FILE_H_INCLUDED
extern int get_file_line(char *result,char *fileName,int lineNumber);//result前少打一個*號,然后就出現段錯誤
#endif

從中可以看到,main.c要用到file.c中的函數,所以引用了file.h頭文件。

如果我們在只編譯main.c文件的話程序會報錯,如圖:

只有當同時編譯main.c和file.c的時候程序才不會報錯:

由此可見多文件編譯的方法為:主文件要包含聲明被引用文件函數的頭文件,編譯的時候主文件和被所有引用的文件要同時編譯才可以。

這樣的方法,在文件很少的時候還可以,在文件很多的時候就不怎么適用了。

當然,多個文件的編譯還有其他方法,比如說makefile,不過如果你是一個一無所知的初學者的話,像codeblock這樣的ide恐怕會更加讓你覺得方便一些。

(三)具體方法

在codeblock當中編譯多個文件十分簡單,只要把所有相關聯的文件添加到一個工程里面就夠了。

使用codeblock編譯實際上和命令行編譯沒有多大的區別,因為它實際上也是自動生成gcc 或g++命令行進行編譯,無須我們手動費勁地輸入命令行。codeblock本身不帶編譯器,使用的是我們系統本身已有的編譯器。

 (1)新建一個工程

新建工程的過程在上一篇的文章中已經說過,把main.c代碼復制粘貼進去就成這樣

(2)把file.c file.h文件復制到工程目錄下。

(3)在codeblock界面當中點擊工程名,選擇add file,將file.c和file.h都添加進工程里面(選中兩個文件后點擊open)

然后出現以下界面

不用管太多,選擇ok就好。

完成后的project界面就是如下這樣子

(4)編譯

點擊build 編譯成功

如圖

我的codeblock編譯產生的命令行是這樣子的

gcc -Wall -g  -c /home/linfen/timer2/main.c -o obj/Debug/main.o
g++  -o bin/Debug/timer2 obj/Debug/file.o obj/Debug/main.o  -lrt -lpthread  /usr/local/lib/libgumbo.a /usr/lib/libpthread.a

但是你們自己編譯的時候應該不會有-lrt -lpthread  /usr/local/lib/libgumbo.a /usr/lib/libpthread.a這個東西。本工程即使沒有-lrt -lpthread  /usr/local/lib/libgumbo.a /usr/lib/libpthread.a也能正常編譯(因為根本就沒有用到那些庫)。

之所以產生-lrt -lpthread  /usr/local/lib/libgumbo.a /usr/lib/libpthread.a與我自己對codeblock編譯器的編譯設定有關,目的是引用第三方庫。不過,本工程並沒有引用第三方庫,所以有沒有-lrt -lpthread  /usr/local/lib/libgumbo.a /usr/lib/libpthread.a都沒有什么關系。

要想這方面了解更多可以繼續看下一篇文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM