内农大《嵌入式基础》实验二 C语言进阶和Makefile

一、 实验目的

  1. 利用多文件编程,掌握Linux环境下C程序的编辑、编译、运行等操作。
  2. 掌握Makefile文件的编写、变量及隐式规则和模式规则的应用。
  3. 掌握Linux环境下main函数的参数。
  4. 掌握各类指针的应用。

二、 实验任务与要求

  1. 根据实验要求编写C语言程序;
  2. 写出各个程序的运行结果并分析; //错误调试 关键代码解释
  3. 根据要求写出Makefile文件;
  4. 利用Makefile文件对多文件程序进行编译。

三、 实验内容

  1. 开发一个计算器,要求多文件编程,文件之间的调用关系如下图:
    在这里插入图片描述

(1) 在inputNum.c文件中输入一组数;
(2) 在Caculator.c文件中在对输入的一组数据进行运算,采用哪些运算请自行设计,但每种运算要单独放在一个自定义函数中,所有运算函数放在Caculator.c文件中;
(3) 在myDisplay.c文件中输出这一组数的各个运算结果。

提示:这里Caculator我就整了一个计算函数sumNums,但实际上可以写好多个,比如求一组数的平均数、求一组数中的最大值、最小值啥的…,这里只写了一个仅为演示

// Caculator.h
int sumNums(int arr[], int n);
// Caculator.c
#include "Caculator.h"
int sumNums(int arr[], int n) {
    int sum = 0;
    int i; 
    for (i=0;i<n;i++){
        sum += arr[i];
    }
    return sum;
}
// myDisplay.h
void display(int a[], int n);
// myDisplay.c
#include <stdio.h>
#include "Caculator.h"
#include "myDisplay.h"

void display(int a[], int n) {
    printf("求和结果为:%d\n", sumNums(a, n));
}
// inputNum.h
void readNums(int arr[], int n);
// inputNum.c
#include <stdio.h>
#include "inputNum.h"
void readNums(int arr[], int n) {
    printf("请输入 %d 个数,以空格隔开:\n", n);
    int i;
    for (i=0;i<n;i++) {
        scanf("%d", &arr[i]);
    }
}
// main.c
#include "inputNum.h"
#include "myDisplay.h"

int main() {
    int a[5];
    readNums(a, 5);
    display(a, 5);
}
  1. 将上述编写的多文件进行预处理、编译、汇编、链接几步来完成多文件的编译。注意每一步骤需要编译的文件扩展名。

2022-11-12 更新:

# 预处理
gcc -E main.c -o main.i
gcc -E myDisplay.c -o myDisplay.i
gcc -E inputNum.c -o inputNum.i
gcc -E Caculator.c -o Caculator。i

gcc -S main.c myDisplay.c inputNum.c Caculator.c # 编译
gcc -c main.c myDisplay.c inputNum.c Caculator.c # 汇编
gcc -o main main.o myDisplay.o inputNum.o Caculator.o # 链接

./main

在这里插入图片描述

在这里插入图片描述

  1. 编写上述多文件程序的Makefile文件。
main: main.o myDisplay.o inputNum.o Caculator.o
	gcc -o main main.o myDisplay.o inputNum.o Caculator.o
main.o: main.c
	gcc -c main.c 
inputNum.o: inputNum.c
	gcc -c inputNum.c
myDisplay.o: myDisplay.c
	gcc -c myDisplay.c
Caculator.o: Caculator.c
	gcc -c Caculator.c

clean:
	rm *.o
  1. 编写上述程序的Makefile文件,要求在文件中使用自定义变量和预定义变量。
OBJ = main.o myDisplay.o inputNum.o Caculator.o
TARGET = main
$(TARGET): $(OBJ)
	gcc -o $@ $^
main.o: main.c
	gcc -c $<
inputNum.o: inputNum.c
	gcc -c $<
myDisplay.o: myDisplay.c
	gcc -c $<
Caculator.o: Caculator.c
	gcc -c $<
	
clean:
	rm $(OBJ) $(TARGET)
  1. 根据隐式规则和模式规则进行Makefile文件的编写。
OBJ = main.o myDisplay.o inputNum.o Caculator.o
TARGET = main
CFLAGS = -Wall -g
$(TARGET): $(OBJ)
	$(CC) $^ -o $@ $(CFLAGS)
%.o: %.c
	$(CC) -c $< -o $@ $(CFLAGS)
clean:
	rm $(OBJ) $(TARGET)
  1. 利用gdb调试工具对上述程序生成的可执行文件进行调试,在各个自定义函数中设置断点,单步执行并查看断点处变量和数组的值。

提示:进行调试前需要用 隐式规则和模式规则版本(上面标号为5的)的 makefile 来构建可执行程序。原因是这个版本的makefile 刚好有 -g 选项

在这里插入图片描述

构建好之后,运行 gdb main 进入调试

在这里插入图片描述

(gdb) list
(gdb) break 6
(gdb) break 7
(gdb) run
(gdb) print a
(gdb) next
(gdb) print a

在这里插入图片描述
在这里插入图片描述

  1. 请利用main函数的参数编写程序实现计算器的功能。
    如:运行程序及结果如下:
    tarena@ubuntu:~/test/d1$ ./t1 5 + 8
    5 + 8=13.000000
    tarena@ubuntu:~/test/d1$ ./t1 9 / 3
    9 / 3=3.000000
// t1.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
    int a = atoi(argv[1]);
    char oper = argv[2][0];
    int b = atoi(argv[3]);
    double ans = 0;
    if (oper == '+') {
        ans = a + b;
    } else if (oper == '-') {
        ans = a - b;
    } else if (oper == '*') {
        ans = a * b;
    } else if (oper == '/') {
        ans = (double)a/b;
    }
    printf("%d%c%d=%.6lf\n",a,oper,b,ans);
}

在这里插入图片描述

  1. 深入理解数组指针和指针数组的含义,利用数组指针、指针数组以及指向指针的指针分别输出二维数组的值,程序结果如下图所示。
    在这里插入图片描述
#include <stdio.h>

int main() {
    int arr[4][4] = {
        {0, 1, 2, 3},
        {4, 5, 6, 7},
        {8, 9, 10, 11},
        {12, 13, 14, 15}
    };
	int i,j;
    printf("使用指针数组的方式访问二维数组arr\n");
    int *pa[4];
    for (i=0;i<4;i++){
        pa[i] = arr[i];
        for (j=0;j<4;j++){
            printf("%d\t", *(pa[i]+j));
        }
        printf("\n");
    }


    printf("使用数组指针的方式访问二维数组arr\n");
    for (i=0;i<4;i++){
        int (*pb)[4] = arr + i;
        for (j=0;j<4;j++){
            printf("%d\t", *(*pb + j));
        }
        printf("\n");
    }

    printf("使用指向指针的指针的方式访问二维数组arr\n");
    for (i=0;i<4;i++){
        int *pc = *(arr + i);
        for (j=0;j<4;j++){
            int *pd = pc + j;
            printf("%d\t", *pd);
        }
        printf("\n");
    }
}

在这里插入图片描述

四、实验总结

好绕一指针!

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

okfang616

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值