You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

执行Makefile编译C项目时遇未定义引用错误,求排查方案

解决C语言项目链接错误:未定义vendingMachine和loanCalc

问题及错误信息

编译项目时出现链接错误,具体输出:

gcc -std=c99 -Wall -Wextra -o main main.o display.o selection.o
selection.o: In function `menu':
selection.c:(.text+0xdd): undefined reference to `vendingMachine'
selection.c:(.text+0x118): undefined reference to `loanCalc'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1

现有文件内容

main.c

#include <stdio.h>
#include "main.h"

int main() {
    char choices[NUM_ITERATIONS];
    double totalAmountSpent = 0.0;

    menu(choices);

    while(userSelect(totalAmountSpent, choices) != 4){
        menu(choices);
    }

    return 0;
}

selection.c

#include <stdio.h>
#include "main.h"

#define NUM_ITERATIONS 3
int menu(char choices[]){
    int prices[NUM_ITERATIONS][2];   //2d array
    double payments[NUM_ITERATIONS];  // 1d array
    double totalAmountSpent = 0.0;
    int count1 = 0;
    int count2 = 0;

    for (int i=0; i < NUM_ITERATIONS; i++) {
        printf("\nMENU:\n");
        printf("1. Vending machine\n");
        printf("2. Loan\n");
        printf("3. Display\n");
        printf("4. Quit\n");
        int userSelection = userSelect(0, choices);
        choices[i] = userSelection;

        switch (userSelection) {
            case 1:
                if (count1 < 3) {
                    choices[i] = 'V';
                    vendingMachine(&totalAmountSpent, prices, choices);
                    count1++;
                }else{
                    printf("You have reached your limit for this menu option.\n");
                    i--;
                }
                break;
            case 2:
                if (count2 < 3){
                    choices[i] = 'L';
                    loanCalc(payments);
                    count2++;
                }else{
                    printf("You have reached your limit for this menu option.\n");
                    i--;
                }
                break;

            case 3:
                displayData(prices, payments, choices);
                break;
            case 4:
                quit(totalAmountSpent);
                break;
            default:
                printf("Invalid choice. Please try again.\n");
                i--;
        }

    }
    return 0;
}

int userSelect(double totalAmountSpent, char choices[]) {
    int userSelection;
    printf("Enter your choice: ");
    scanf("%d", &userSelection);
    return userSelection;
}

display.c

#include <stdio.h>
#include "main.h"

#define NUM_ITERATIONS 3
void displayData(int prices[][2], double payments[],char choices[]){

    printf("\nChoices made:\n");
    for (int i = 0; i < NUM_ITERATIONS; i++){
        printf("Iteration %d: %c\n", i +1, choices[i]);
    }

    printf("\nResults:\n");
    for(int i=0; i < NUM_ITERATIONS; i++){
        printf("Iteration %d - Price: %d cents, Loan Payment: $%.2f\n", i+1, prices[i][0], payments[i]);
    }
}

void quit(double totalAmt) {
    printf("Total amount spent on the vending machine: $%.2f\n", totalAmt);
}

main.h

#ifndef MAIN_H
#define MAIN_H

#define NUM_ITERATIONS 3

int menu(char choices[]);
int userSelect(double totalAmountSpent, char choices[]); // 修正参数名拼写错误:chpices -> choices
void vendingMachine(double *totalAmt, int prices[][2], char choices[]);
void loanCalc(double payments[]);
void displayData(int prices[][2], double payments[], char choices[]);
void quit(double totalAmt);

#endif // MAIN_H

当前Makefile

CC = gcc
CFLAGS = -std=c99 -Wall -Wextra

all: main

main: main.o display.o selection.o
        $(CC) $(CFLAGS) -o main main.o display.o selection.o

main.o: main.c main.h
        $(CC) $(CFLAGS) -c main.c

display.o: display.c main.h
        $(CC) $(CFLAGS) -c display.c

selection.o: selection.c main.h
        $(CC) $(CFLAGS) -c selection.c

clean:
        rm -f main *.o

问题分析与解决

核心问题

链接错误的根源是:vendingMachine和loanCalc仅在main.h中声明了函数原型,但没有在任何.c文件中编写具体实现代码,链接器无法找到这两个函数的二进制执行代码。

解决步骤

  1. 实现缺失的函数

    • 创建vending.c文件,实现vendingMachine函数(示例逻辑):
      #include <stdio.h>
      #include "main.h"
      
      void vendingMachine(double *totalAmt, int prices[][2], char choices[]) {
          // 模拟售货机购买流程:记录商品价格并累加总花费
          int price;
          printf("Enter item price (cents): ");
          scanf("%d", &price);
          // 找到当前要记录的迭代索引
          int idx = 0;
          while (idx < NUM_ITERATIONS && choices[idx] != 'V') idx++;
          if (idx < NUM_ITERATIONS) {
              prices[idx][0] = price;
              *totalAmt += price / 100.0;
              printf("Added $%.2f to total spent\n", price / 100.0);
          }
      }
      
    • 创建loan.c文件,实现loanCalc函数(示例逻辑):
      #include <stdio.h>
      #include <math.h>
      #include "main.h"
      
      void loanCalc(double payments[]) {
          // 模拟贷款月供计算流程
          double principal, rate;
          int months;
          printf("Enter loan principal: $");
          scanf("%lf", &principal);
          printf("Enter annual interest rate (%%): ");
          scanf("%lf", &rate);
          printf("Enter loan term (months): ");
          scanf("%d", &months);
      
          double monthlyRate = rate / 100 / 12;
          double payment = principal * monthlyRate * pow(1 + monthlyRate, months) / (pow(1 + monthlyRate, months) - 1);
          // 找到第一个未记录月供的位置
          int idx = 0;
          while (idx < NUM_ITERATIONS && payments[idx] != 0) idx++;
          if (idx < NUM_ITERATIONS) {
              payments[idx] = payment;
              printf("Monthly payment: $%.2f\n", payment);
          }
      }
      

    注:可根据实际需求调整函数逻辑,比如给loanCalc增加索引参数,直接将结果写入对应迭代的位置。

  2. 更新Makefile
    在编译规则中加入新生成的.o文件,修改后的Makefile:

    CC = gcc
    CFLAGS = -std=c99 -Wall -Wextra
    LIBS = -lm  # 引入数学库,因为loanCalc用到了pow函数
    
    all: main
    
    main: main.o display.o selection.o vending.o loan.o
            $(CC) $(CFLAGS) -o main main.o display.o selection.o vending.o loan.o $(LIBS)
    
    main.o: main.c main.h
            $(CC) $(CFLAGS) -c main.c
    
    display.o: display.c main.h
            $(CC) $(CFLAGS) -c display.c
    
    selection.o: selection.c main.h
            $(CC) $(CFLAGS) -c selection.c
    
    vending.o: vending.c main.h
            $(CC) $(CFLAGS) -c vending.c
    
    loan.o: loan.c main.h
            $(CC) $(CFLAGS) -c loan.c
    
    clean:
            rm -f main *.o
    
  3. 修正笔误
    原main.h中userSelect的参数名拼写错误:chpices改为choices,避免编译警告。

完成以上步骤后,重新执行make命令即可正常编译链接。

内容的提问来源于stack exchange,提问作者elix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:24:53