创建头文件并在 C 中测试它

create header file and test it in C

我在同一目录中有文件:

selection_sort.c

#include <cs50.h>
#include "selection_sort.h"

void selection_sort(int values[], int n)
{
    for (int i = 0; i < n; i++)
    {
        int min_index = i;
        for (int j = i+1; j < n; j++)
        {
            if (values[j] < values[min_index])
            {
                min_index = j; 
            }
        }

        int temp = values[i];
        values[i] = values[min_index];
        values[min_index] = temp; 
    }
}

注意:这个 selection_sort() 在我以前的使用中工作正常。

selection_sort.h

#include <cs50.h>
void selection_sort(int values[], int n);

最后一个文件为测试文件,命名为 test_selection_sort.h

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

#include "selection_sort.h"


int test_array[] = {2,4,7,5,9,1,3,6,8};

int main()
{
    int size = sizeof(test_array);
    selection_sort(test_array,size);
    for (int i = 0; i < size; i++)
    {
        printf ("sorted %d", test_array[i]);
    }
}

但是当我编译时它显示对'selection_sort'的未定义引用:

$ make test_selection_sort

....undefined reference to `selection_sort'

我想了解定义头文件的问题和我的错误使用?


编辑:

我现在可以制作文件了:

$gcc -o selection selection_sort.c test_selection_sort.c
$./selection

该错误消息很可能意味着您未能包含编译 selection_sort.c 生成的 .o 文件。仅仅包含头文件是不够的,尽管这很重要。

 gcc -c selection_sort.c
 gcc -c test_selection_sort.c
 gcc -o test_selection_sort selection_sort.o test_selection_sort.o

还有很多其他方法可以完成同样的事情。如果您要创建多个实用函数,请考虑使用 ar 工具将它们全部放入对象库,然后使用 -l 选项包含该库。

可能您没有编译 correctly.Fix 您的 makefile。 试试这个:

OBJS = selection_sort.o  test_selection_sort.o
TARGET =  test_selection_sort
CC = gcc
MODE = -std=c99
DEBUG = -g
DEPS = selection_sort.h
CFLAGS =  -Wall -c $(DEBUG)
LFLAGS =  -Wall $(DEBUG)

%.o: %.c $(DEPS)
    $(CC) $< $(CFLAGS) $(MODE)

all: $(OBJS)
    $(CC) $^ $(LFLAGS) -o $(TARGET) $(MODE)

只需输入

make

C 构建系统是一个古老的系统,包含文件只是 包含 在源文件中通常用于声明外部函数或全局变量。但它没有向 linker 提供有关需要哪些模块的提示。另一方面,其他语言,如 C#、Java 或 Python import 模块,它们既声明了编译部分的标识符,又声明了 linker 已经编译好的模块将被添加到程序中。

在 C 中,程序员必须:

  • 为编译器使用包含文件
  • 明确地link不同的编译单元或库。

这就是 makefile 可以派上用场的地方,它只需声明一次如何构建可执行文件并在源代码被修改时自动重建目标文件。

或者,您可以使用以下方法构建:

cc test_selection.c selection_sort.c -o test_selection

但效率较低,因为即使一个文件没有更改,它也会始终编译两个文件