可以在隔离环境中编译任何 .c 文件吗?也就是说,没有主函数可以编译吗?

5

我目前有一个类似库的.c文件(将在下面显示)。我对它有两个问题:

  1. If I want to see if it compiles well for itself, how can I do it? If I try to gcc it, it will always give a "no main" error, which makes sense, but raises the problem of knowing if a given .c file will compile well or not in "isolation". Can I safely conclude that if the only error raised by the compiler is the "no main" one, my file is fine? An example of where compiling .c files in isolation could be nice would be to determine which includes are in excess, in here.

  2. Is there a point in a simple file like this to define a header with its method / struct declarations and then have such tiny .c file with the code implementation in it?

    #ifndef SEMAFOROS
    #define SEMAFOROS
    
    
    #include <signal.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <semaphore.h>
    
    
    typedef struct {
        sem_t* id;
        char* nome;
    } Semaforo;
    
    
    inline void lock(Semaforo* semaforo) {
        sem_wait(semaforo->id);
    }
    
    
    inline void unlock(Semaforo* semaforo) {
        sem_post(semaforo->id);
    }
    
    
    Semaforo* criarSemaforo(char* nome) {
        Semaforo* semaforo = (Semaforo*)malloc(sizeof(Semaforo));
        semaforo->id = sem_open(nome, O_CREAT, 0xFFFFFFF, 1);
        semaforo->nome = nome;
    }
    
    
    void destruirSemaforo(Semaforo* semaforo) {
        sem_close(semaforo->id);
        sem_unlink(semaforo->nome);
    
    
    <pre><code>free(semaforo);
    

    }
    #endif

谢谢

3个回答

11

若要编译而不链接(不需要主入口点):

cc -c file.c -o file.o

即使是定义将从其他源文件调用的例程的小文件,您仍然需要一个头文件。头文件是编译器在链接器将所有内容捆绑在一起之前了解例程接口的方式。如果没有外部函数的声明,那么编译器就必须对参数的数据类型做出(通常错误的)假设。您可以在每个使用它们的源文件中声明函数,但头文件的要点在于您只需在头文件中声明一次即可。


头文件不仅仅是用来声明一次的,它们还应该被包含在实现文件的顶部,以便编译器检查头文件没有其他依赖关系,并且声明和定义是一致的。另外,每个对象最好都有一个测试实现文件,因为即使编译一个.o文件也无法测试一些未使用的功能(例如C++模板成员函数)。 - Tony Delroy

4

-c选项是gcc编译器中的一个选项,它可以将一个.c文件编译成一个.o文件。看起来你缺少了这个选项。

对于你的第二个问题,答案是“当然”。在所有想要使用某个共享函数的.c文件中都手动输入extern变量是一个好习惯。每个小的.h文件都有帮助。


对于第二个问题,我想知道为什么! - devoured elysium

2

对于第二个问题,我想知道为什么!

回答第二点,将声明保留在头文件中可以帮助您避免以下情况。

您决定在file.c中跟踪您的鸡:

int number_of_chickens;

file2.c中,您决定将鸡的数量表示为double而不是int,但您忘记更新file.c
extern double number_of_chickens;
double count_chickens() {
    return number_of_chickens;
}

void add_to_chickens(double how_many) {
    number_of_chickens += how_many;
}

这将编译得很好。 链接器将把 number_of_chickens 视为引用 file.c 中的 4 位 int 和 file2.c 中的 8 位 double 的名称。
如果调用 count_chickens 函数,它将返回垃圾(双精度的高 32 位将填充为 int number_of_chickens 的内容,低 32 位将未定义 - 在内存中跟在 number_of_chickens 后面的任何内容)。
更糟糕的是,当您在 file2.c 中调用 add_to_chickens(1) 时,您将向一个 4 字节的存储位置写入 8 个字节,肯定会造成混乱,但不一定会导致运行时错误(至少不是立即)。
如果将外部声明保存在公共头文件中,则会立即出现编译时错误。 如果不这样做,您将在发货后的 3 个月内遇到无法解释的不稳定性。

在头文件中包含原型不会导致编译时错误。它将导致从intdouble的正确自动转换发生,并使代码正常工作。 - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接