GCC背后的故事&C程序常量变量的地址分配

目录

一、题目要求

二、过程呈现

1、用gcc生成静态库和动态库

1)代码文件准备

2)静态库的使用

3)动态库的使用

2、静态库文件与动态库文件的生成与使用

1)代码准备

2)静态库的生成与使用

3、x2x、x2y程序生成静态库文件与动态文件并进行链接

1)代码实现

2)生成静态库

3)生成动态库

4)与之前做对比

4、linux常用命令的仿做与gcc编译工具集中各软件的用途

1)gcc编译工具集中各软件的用途

2)linux常用命令的仿做

5、C程序变量常量的地址分配

1)Ubuntu系统验证

2)stm32下验证

三、总结

四、参考资料


一、题目要求

1. 学习并掌握可执行程序的编译、组装过程。学习任务如下:

1)阅读、理解和学习材料“用gcc生成静态库和动态库.pdf”和“静态库.a与.so库文件的生成与使用.pdf”,请在Linux系统(Ubuntu)下如实仿做一遍。

2)在第一次作业的程序代码基础进行改编,除了x2x函数之外,再扩展写一个x2y函数(功能自定),main函数代码将调用x2x和x2y ;将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件;将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件, 然后用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小。

3)将x2x、x2y目标文件用 ar工具生成1个 .so 动态库文件, 然后用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录文件的大小,并与之前做对比。

2. Gcc不是一个人在战斗。请说明gcc编译工具集中各软件的用途,了解EFF文件格式。学习任务如下:阅读、理解和学习材料“Linux GCC常用命令.pdf”和“GCC编译器背后的故事.pdf”,如实仿做一遍。

3.编写一个C程序,重温全局常量、全局变量、局部变量、静态变量、堆、栈等概念,在Ubuntu(x86)系统和STM32(Keil)中分别进行编程、验证(STM32 通过串口printf 信息到上位机串口助手) 。1)归纳出Ubuntu、stm32下的C程序中堆、栈、全局、局部等变量的分配地址,进行对比分析;2)加深对ARM Cortex-M/stm32F10x的存储器地址映射的理解。

二、过程呈现

1、用gcc生成静态库和动态库

1)代码文件准备

hello代码

我们可以在终端上使用vim对hello代码进行编写分别输入vi hello.h,vi hello.c,vi main.c,在终端上输入如下

具体代码如下

hello.h

#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif//HELLO_H

hello.c

#include<stdio.h>
void hello(const char *name)
{
	printf("Hello %s\n",name);
}

main.c

#include"hello.h"
int main()
{
	hello("everyone");
	return 0;
}

接下来我们便使用gcc编译得到.o文件,终端输入gcc -c hello.c,具体操作如下

2)静态库的使用

(1)静态库的创建与使用

我们在终端输入ar -crv libmyhello.a hello.o即可创建静态库

然后我们在终端输入以下命令

gcc -o hello main.c -L. -lmyhello

然后编译程序可得到输出,如下

(2)静态库的特点验证

若删除静态库文件,在运行文件,我们发现其仍然可以正常运行,则表明静态库与程序执行文件没有联系,如下

3)动态库的使用

动态库的创建

终端输入gcc -shared -fPIC -o libmyhello.so hello.o即可创建动态库我们也可在终端输入ls查看是否创建完毕以及创建目录,具体步骤演示如下

动态库的使用

此时我们输入./hello即可输出所编译的结果

2、静态库文件与动态库文件的生成与使用

1)代码准备

与前面一样,我们还是在vim上面完成相关程序的编写,终端输入如下代码

vi A1.c,

vi A2.c,

vi A.h

vi test.c

在此之前我们可以新建一个目录,并将上诉程序放在该目录下

2)静态库的生成与使用

我们在终端输入ar crv libfile.a A1.o A2.o,然后输入gcc -o test test.c libfile.a,,具体步骤如下

此时出现错误,我们要将test文件中的exit(0)改为return 0即可,然后输入./test可得到输出

3)动态库的使用

输入

gcc -shared -fPIC -o libfile.so A1.o A2.o
gcc -o test test.c libfile.so

./test

具体步骤与结果如下

3、x2x、x2y程序生成静态库文件与动态文件并进行链接

1)代码实现

先创建一个新目录test3,并将要编写的代码放在该目录下

x2x此前实验已经编译好

输入vi sub2.c

编写如下代码

float x2y(int a,int b)
{
	float c=0;
	c=a/b;
	return c;
}

输入vi sub.h,编写如下代码

#ifndef SUB_H
#define SUB_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif

输入vi main.c

#include<stdio.h>
#include"sub.h"
void main()
{
	int a,b;
	printf("Please input the value of a:");
	scanf("%d",&a);
	printf("Please input the value of b:");
	scanf("%d",&b);
	printf("a+b=%.2f\n",x2x(a,b));
	printf("a/b=%.2f\n",x2y(a,b));
}

终端输入gcc -c sub1.c sub2.c

2)生成静态库

输入ar crv libsub.a sub1.o sub2.o

gcc -o main main.c libsub.a

我们还可以输入./main完成静态库的使用,运行程序,上述的全部操作如下所示

3)生成动态库

终端输入

gcc -shared -fPIC libsub.so sub1.o sub2.o
gcc -o main main.c libsub.so

4)与之前做对比

静态库

动态库

4、linux常用命令的仿做与gcc编译工具集中各软件的用途

1)gcc编译工具集中各软件的用途

GCC:

GCC(GNU C Compiler)是编译工具。本文所要介绍的将 C/C++语言编写的程序转换成为处理器能够执行的二进制代码的过程即由编译器完成。

Binutils:

一组二进制程序处理工具,包括:addr2line、ar、objcopy、objdump、as、ld、ldd、readelf、 size 等。这 一组工具 是开发和 调试不可 缺少的工具,分别简介如下:

(1) addr2line:用 来将程序 地址转 换成其所 对应的程 序源文件及所对应的代码行,也可以得到所对应的函数。该工具将帮助调试器在调试的过程中定位对应的源代码位置。

(2) as:主要用于汇编,有关汇编的详细介绍请参见后文。

(3) ld:主要用于链接,有关链接的详细介绍请参见后文。

(4) ar:主要用于创建静态库。为了便于初学者理解,在此介绍动态库与静态库的概念:

(5) ldd:可以用于查看一个可执行程序依赖的共享库。

(6) objcopy:将一种对象文件翻译成另一种格式,譬如将.bin 转换成.elf、或者将.elf 转换成.bin 等。

(7) objdump:主要的作用是反汇编。有关反汇编的详细介绍,请参见后文。

(8) readelf:显示有关 ELF 文件的信息,请参见后文了解更多信息。

(9) size:列出可执行文件每个部分的尺寸和总尺寸,代码段、数据段、总大小等,请参见后文了解使用 size

C 运行库

   C 语言标准主要由两部分组成:一部分描述 C 的语法,另一部分描述C 标准库。C 标准库定义了一组标准头文件,每个头文件中包含一些相关的函数、变量、类型声明和宏定义,譬如常见的 printf 函数便是一个 C 标准库函数,其原型定义在 stdio 头文件中。 C 语言标准仅仅定义了 C 标准库函数原型,并没有提供实现。因此,C 语言编译器通常需要一个 C 运行时库(C Run Time Libray,CRT)的支持。C 运行时库又常简称为 C 运行库。与 C 语言类似,C++也定义了自己的标准,同时提供相关支持库,称为 C++运行时库。

2)linux常用命令的仿做

简单编译

示例程序使用vim进行编写,输入

vi test.c,程序如下

#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}

其一步到位的编译指令为

gcc test.c -o test

终端输入gcc -E test.c -o test.i 或 gcc -E test.c,进行预处理

终端输入gcc -S test.i -o test.s编译为汇编代码

终端输入gcc -c test.s -o test.o进行汇编

终端输入gcc test.o -o test可以进行连接

所有步骤如下所示

5、C程序变量常量的地址分配

1)Ubuntu系统验证

Ubuntu系统仍然使用vim对程序进行编译

终端输入vi text.c,编写如下代码

#include <stdio.h>
#include <stdlib.h>
//定义全局变量
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
	printf("hello");
	printf("%d",a);
	printf("\n");
}
 
int main( )
{   
	//定义局部变量
	int a=2;
	static int inits_local_c=2, uninits_local_c;
    int init_local_d = 1;
    output(a);
    char *p;
    char str[10] = "lmy";
    //定义常量字符串
    char *var1 = "1234567890";
    char *var2 = "qwertyuiop";
    //动态分配
    int *p1=malloc(4);
    int *p2=malloc(4);
    //释放
    free(p1);
    free(p2);
    printf("栈区-变量地址\n");
    printf("                a:%p\n", &a);
    printf("                init_local_d:%p\n", &init_local_d);
    printf("                p:%p\n", &p);
    printf("              str:%p\n", str);
    printf("\n堆区-动态申请地址\n");
    printf("                   %p\n", p1);
    printf("                   %p\n", p2);
    printf("\n全局区-全局变量和静态变量\n");
    printf("\n.bss段\n");
    printf("全局外部无初值 uninit_global_a:%p\n", &uninit_global_a);
    printf("静态外部无初值 uninits_global_b:%p\n", &uninits_global_b);
    printf("静态内部无初值 uninits_local_c:%p\n", &uninits_local_c);
    printf("\n.data段\n");
    printf("全局外部有初值 init_global_a:%p\n", &init_global_a);
    printf("静态外部有初值 inits_global_b:%p\n", &inits_global_b);
    printf("静态内部有初值 inits_local_c:%p\n", &inits_local_c);
    printf("\n文字常量区\n");
    printf("文字常量地址     :%p\n",var1);
    printf("文字常量地址     :%p\n",var2);
    printf("\n代码区\n");
    printf("程序区地址       :%p\n",&main);
    printf("函数地址         :%p\n",&output);
    return 0;
}
 

在Ubuntu系统中如下

终端输入

gcc test.c -o text

./test

输出结果如下

 Ubuntu在栈区和堆区的地址值都是从上到下增长的

2)stm32下验证

在keil中进行改写

编译,如下

STM32 在栈区和堆区的地址值是从上往下的在减小与Ubuntu下刚好相反。

三、总结

这次作业的内容有点多,对自己来说难度也较大,有些方面自己完成的也不是很好,还是需要查阅参考资料辅助自己才可以完成较多内容,不过总的来时,它对我的提升还是较大的,希望下次可以做到更好。

四、参考资料

https://blog.csdn.net/qq_43279579/article/details/109026927

http://t.csdnimg.cn/gDwye

https://mooc1.chaoxing.com/ueditorupload/read?objectId=b9616c5b28b9b0b12e4df8411148087e&fileOriName=GCC%25E7%25BC%2596%25E8%25AF%2591%25E5%2599%25A8%25E8%2583%258C%25E5%2590%258E%25E7%259A%2584%25E6%2595%2585%25E4%25BA%258B.pdf

https://mooc1.chaoxing.com/ueditorupload/read?objectId=dc36405faf8e7dc66d657fcc6b780cd7&fileOriName=%25E7%2594%25A8gcc%25E7%2594%259F%25E6%2588%2590%25E9%259D%2599%25E6%2580%2581%25E5%25BA%2593%25E5%2592%258C%25E5%258A%25A8%25E6%2580%2581%25E5%25BA%2593.pdf

https://mooc1.chaoxing.com/ueditorupload/read?objectId=07cf0524899ab88f4d59af8e05a94d8a&fileOriName=%25E9%259D%2599%25E6%2580%2581%25E5%25BA%2593.a%25E4%25B8%258E.so%25E5%25BA%2593%25E6%2596%2587%25E4%25BB%25B6%25E7%259A%2584%25E7%2594%259F%25E6%2588%2590%25E4%25B8%258E%25E4%25BD%25BF%25E7%2594%25A8.pdf

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值