Linux C语言编程基础
Linux C语言编程基础
教材2.10编程:
实践内容:建立项目目录:
实践截图:
实践内容:ESc iso 练习:
C语言运行的过程主要是:C源程序->编译预处理->编译->优化程序->汇编程序->链接程序->可执行文件
-E练习:
实践截图:
打开main.i文件查看预处理结果:
这里可以看出编译预处理阶段,读取C源程序,对其中的预处理指令(以#开头的指令)和特殊符号进行处理。或者说是扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。预处理指令会读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行转换。预处理过程还会删除程序中的注释和多余的空白字符。
-S练习:
打开main.s文件查看:
经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,以及C语言的关键字,如main, if , else , for , while , { , } , + , - , * , \ 等等。
编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。
经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器指令,方可能被机器执行。
-c练习:
打开main.o文件查看:
汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。
链接过程:
实践内容:静态库制作与调用:
只需要按照老师上课讲的步骤一步一步来就ok
实践内容:动态库制作与调用:
将生成的动态库复制到/usr/lib里:
随后执行命令:
可以看出程序成功运行。
实践内容:gdb练习:
设置四种断点:
查看四种断点:
调试运行程序:
单步调试与直接跳过等指令:
实践内容:makefile的编写与使用:
这里的在练习makefile的使用时,我用的是数据结构课上的实验内容:基于链表的大数运算
type.h头文件:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MIN 200
#define MAX 40000
#define LEN sizeof(struct DNode)
/*********************结构体定义*************************/
typedef struct DNode
{
int data;
struct DNode * next;
}DNode;
main函数:
#include "type.h"
/***********************大数加法函数*************************/
void addNUM(DNode *p1,DNode *p2,int count)
{
int result[MAX]={0}; //存放结果的数组
int i,k,m,n;
int flag=count;
for (i = 0; i < count; i++)
{
m = p1->data + p2->data; //遍历链表,利用竖式运算
result[i] = m; //将处理后的加和结果存放到结果数组中
k = i; //记录数组长度
p1 = p1->next; //链表指针指向下一位
p2 = p2->next;
}
for ( n = 0; n < flag; n++) //处理数组中的结果进位
{
result[n+1]=result[n+1]+result[n]/10; //进位操作
result[n]=result[n]%10; //如果大于10,将结果处理为个位数数字
}
for ( i = k; i >= 0; i--) //因为加法操作得到的结果位数可能为e+1,也可能为e
{
if (result[k+1]==0) //所以结果数组中存储的逆序第一位可能为0
{
n--; //将0跳过,打印后面的结果
result[flag]=1;
}
printf("%d",result[i]);
}
printf("\n");
}
addNUM函数:
#include "type.h"
/***********************大数加法函数*************************/
void addNUM(DNode *p1,DNode *p2,int count)
{
int result[MAX]={0}; //存放结果的数组
int i,k,m,n;
int flag=count;
for (i = 0; i < count; i++)
{
m = p1->data + p2->data; //遍历链表,利用竖式运算
result[i] = m; //将处理后的加和结果存放到结果数组中
k = i; //记录数组长度
p1 = p1->next; //链表指针指向下一位
p2 = p2->next;
}
for ( n = 0; n < flag; n++) //处理数组中的结果进位
{
result[n+1]=result[n+1]+result[n]/10; //进位操作
result[n]=result[n]%10; //如果大于10,将结果处理为个位数数字
}
for ( i = k; i >= 0; i--) //因为加法操作得到的结果位数可能为e+1,也可能为e
{
if (result[k+1]==0) //所以结果数组中存储的逆序第一位可能为0
{
n--; //将0跳过,打印后面的结果
result[flag]=1;
}
printf("%d",result[i]);
}
printf("\n");
}
mulnum函数:
#include "type.h"
/*******************大数乘法函数**********************/
void mulnum(DNode *head1,DNode *head2,int len1,int len2)
{
DNode *p1,*p2;
int i,j,n = 0;
int count = 1;
int flag = len1+len2-1; //乘法竖式运算结果位数为两个大整数数字位数减一
int result[MAX]={0};
int temp = 0;
p2 = head2;
for (i = 0; i < len2; i++) //for循环嵌套计算各个位数相乘
{
p1=head1;
for ( j = 0; j < len1; j++)
{
temp = (p1->data)*(p2->data); //将当前链表结点所存数据相乘结果存储下来
result[i+j]=result[i+j]+temp; //直接将结果存进数组
p1=p1->next; //指针指向下一位
}
p2=p2->next; //指针指向下一位
}
for ( n = 0; n < flag+1; n++) //处理数组中的结果进位
{
result[n+1]=result[n+1]+result[n]/10; //进位操作
result[n]=result[n]%10; //如果大于10,将结果处理为个位数数字
}
for ( n = flag; n >= 0; n--) //因为乘法操作得到的结果位数可能为len1+len2-1,也可能为len1+len2
{
if (result[flag]==0) //所以结果数组中存储的逆序第一位可能为0
{
n--; //将0跳过,打印后面的结果
result[flag]=1;
}
printf("%d",result[n]);
}
printf("\n");
}
decnum函数:
#include "type.h"
/******************************大数减法函数****************************/
void decnum(DNode *p1,DNode *p2,int count,int a[],int b[],int len1,int len2)
{
int result[MAX]={0}; //结果数组
int i,k,m,flag;
if (len1==len2) //如果链表1与链表2长度相同
{
for ( i = 0; i < len1+1; i++) //判断两个链表中所存大整数的大小
{
if (a[i]>b[i])
{
flag=1; //如果a数组中所存大整数大于b数组,则将flag设置为1
break;
}
else if(a[i]<b[i])
{
flag=0; //如果小于则设置为0
break;
}
}
}
else if (len1>len2){flag=1;} //数组长度不同情况下判断大整数大小
else{flag = 0;}
for (i = 0; i < count; i++)
{
if (flag==1) //如果大整数a大于b
{
m = p1->data - p2->data; //直接利用大数加法思想进行计算
if (m < 0)
{
m = 10+m;
(p1->next)->data --; //借位
}
}
if (flag==0)
{
m = p2->data - p1->data; //将顺序调换,让大的减小的
if (m < 0)
{
m = 10+m;
(p2->next)->data --;
}
}
result[i] = m;
k = i;
p1 = p1->next;
p2 = p2->next;
}
if (flag==0){printf("-");} //如果是负数则打印‘-’号
while (result[k]==0) //如果结果数组末尾有一堆0,就把他们全跳过。
{
k--;
}
for ( i = k; i >= 0; i--)
{
printf("%d",result[i]);
} //逆序打印结果
printf("\n");
}
creat函数:
#include "type.h"
//************************链表创建函数***********************************/
DNode * creat (int A[], int B)
{
int i;
struct DNode *head, *p1, *p2;
p1 = p2 = (DNode *) malloc (LEN);
for (i = B; i > 0; i--) //将数据倒序存放在链表中
{
p1->data = A[i]; //将数值存放在结点内
if(i == B)
{head = p1;}
else
{p2->next = p1;}
p2 = p1; //指针指向下一位
p1 = (DNode *) malloc (LEN); //给临时结点分配空间
}
return head; //返回头结点
}
makefile内容:
testmain: libtestmymath.a include/type.h
gcc src/main.c -o bin/testmain -I/home/wpy/桌面/dashu/include -Llibs -ltestmymath
libtestmymath.a: addNUM.o mulnum.o decnum.o creat.o
ar rcvs -o libs/libtestmymath.a libs/addNUM.o libs/decnum.o libs/creat.o libs/mulnum.o
addNUM.o: src/addNUM.c include/type.h
gcc -c src/addNUM.c -I/home/wpy/桌面/dashu/include -o libs/addNUM.o
decnum.o: src/decnum.c include/type.h
gcc -c src/decnum.c -I/home/wpy/桌面/dashu/include -o libs/decnum.o
mulnum.o: src/mulnum.c include/type.h
gcc -c src/mulnum.c -I/home/wpy/桌面/dashu/include -o libs/mulnum.o
creat.o: src/creat.c include/type.h
gcc -c src/creat.c -I/home/wpy/桌面/dashu/include -o libs/creat.o
clear:
rm libs/*.o
start:
bin/testmain
借鉴了书上关于makefile的内容,可以实现静态库的制作与调用,以及程序的运行:
实践截图:
本次实践内容全部在openeuler系统上进行,openeuler系统操作起来还是比较麻烦的,而且由于缺少很多依赖,导致我在安装中文环境时总是出错。并且找不到原因在哪里,看来还是需要深入学习一下openeuler系统的操作。