【问题标题】:create header file and test it in C创建头文件并在C中测试它
【发布时间】:2017-07-31 14:30:29
【问题描述】:

我在同一目录中有文件:

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

【问题讨论】:

  • int min_index = values[i]; --> int min_index = i;
  • int size = sizeof(test_array); --> int size = sizeof(test_array)/sizeof(*test_array);
  • values[min_index] temp; --> values[min_index] = temp;
  • 问题嵌套在您的 Makefile 中的某处。请将其添加到您的问题中以获得进一步的帮助。
  • 显示Makefile

标签: c segmentation-fault header-files cs50


【解决方案1】:

错误消息很可能意味着您未能包含编译 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 选项包含该库。

【讨论】:

    【解决方案2】:

    C 编译系统是一个旧系统,一个包含文件只是简单地包含 在源文件中,用于声明外部函数或全局变量。但它没有提示链接器需要哪些模块。另一方面,其他语言,如 C#、Java 或 Python import 模块,它们都为编译部分声明标识符,但也声明链接器将哪些已编译的模块添加到程序中。 p>

    在 C 语言中,程序员必须两者兼有:

    • 为编译器使用包含文件
    • 显式链接不同的编译单元或库。

    通过只声明一次如何构建可执行文件并在修改源文件时自动重新构建目标文件,makefile 可以变得很方便。

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

    cc test_selection.c selection_sort.c -o test_selection
    

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

    【讨论】:

    • 这对我来说有点不知所措。我正在学习CS50课程。我没有看到他们包含 .o 文件。
    【解决方案3】:

    可能你没有正确编译。修复你的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
    

    【讨论】:

    • 我很难理解这些都是什么意思?
    • 我以前从未见过这些。未来需要学习很多东西。
    • @Amy:当您使用make 时,这是非常可行的方法。您的 makefile 列出了创建可执行文件所需的目标文件。以后,你自己的库中可能会有一些代码,类似于你也使用的-lcs50 库。
    • @Amy:makefile 很繁琐;诸如$(CC) $&lt; $(CFLAGS) $(MODE) 之类的规则(配方)行必须由实际的制表符缩进,而不仅仅是空格。 — 另外,一般来说,我会将-c 选项保留在CFLAGS 之外,并直接在$(CC) -c $&lt; $(CFLAGS) $(MODE) 中使用它,我也会将$(CFLAGS) 传递给链接行。不过,这与您的直接问题无关。
    • @Amy 正如乔纳森所说,您必须使用制表符而不是空格。Make 仅将制表符识别为分隔符。本教程阐明了这个 makefile 中的所有内容。cs.colby.edu/maxwell/courses/tutorials/maketutor
    猜你喜欢
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多