C语言程序是如何执行的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言程序是如何执行的相关的知识,希望对你有一定的参考价值。

C语言怎么运行,以linux举例:
1、编写好源代码example.c;假设是放在目录/home/user/下面;
2、进入/home/user/目录,编译源代码:gcc example.c -o example,如果没有编译错误,将生成执行文件example;
3、在当前目录下输入./example,就可以运行了;
当然还有在TC和VC下运行的方法,那些都是图形化的,比较简单,唯一需要注意的是在TC下运行,要设定好环境变量
参考技术A 从main函数开始执行,从main结束 参考技术B 从main()开始执行;对于嵌入式系统而言,先执行.s文件,这是启动文件,对系统进行初始化
然后调用main()函数
在执行main()过程中,调用函数,函数调用后返回main(),直到main()执行完毕
因此C是面向过程的,函数是C的结构模块追问

C语言整体结构是什么,请举一形象的例子。

追答

#include //头文件包含
void function1(void); //函数声明
void function2(void); //函数声明

int main() //主函数

function1(); //函数调用
function2(); //函数调用
return 1;


void function1(void) //函数定义
printf("hello world1\n");

void function2(void) //函数定义

printf("hello world2\n");

参考技术C 主函数是main()所以是从main()开始执行、、

C程序是如何跑起来的01 —— 普通可执行文件的构成

学习目的

  • 程序烧到什么地方?
  • 程序加载到内存什么地方?
  • 程序如何执行?

一、编译环境搭建

ubuntu 20.04使用arm-linux-gnueabihf-gcc 7.5.0。

二、程序源码

main.c:

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

int main(int argc, char *argv[])

    int a, b;
    static int local_val = 2;
    static int uninit_local_val;

    a = add(2, 3);
    b = sub(5, 4);

    printf("a = %d\\n", a);
    printf("b = %d\\n", b);

    return 0;

calc.h:

#ifndef _CALC_H_
#define _CALC_H_

int add(int a, int b);
int sub(int a, int b);

#endif

calc.c:

#include "calc.h"

int add(int a, int b)

    return a + b;


int sub(int a, int b)

    return a - b;

编译:

arm-linux-gnueabihf-gcc main.c calc.c

交叉编译生成 a.out 可执行文件,文件类型是32位ARM平台可执行文件。

三、readelf工具

readelf工具由编译器提供,用来列出关于可执行文件的内容的相关信息

使用格式如下:

Usage: readelf <option(s)> elf-file(s)

(1)查看可执行文件的头部 信息

  • -h:用于列出ELF文件的头部信息,包括可执行文件运行的平台、软件版本、程序入口地址,以及program headers、section header等信息;


(2)查看section header

  • -S:用于列出程序中section的头部信息

四、可执行文件的组成结构

一个可执行文件由一系列section构成,section称为段,包括:代码段text、只读数据段rodata、数据段data、bss段等。

每个section用一个section header描述,包括段名、段的类型、段的起始地址、段的偏移、段的大小等。

将可执行文件的所有section header集合到一起就是section header table,使用readelf 的 -S 参数查看的就是该表。

在程序编译的时候,对C语言代码中定义的函数、变量、未初始化的全局变量进行编译分类,放置在不同的段中:

  • 普通代码翻译成二进制放到代码段(text)中
  • 常量放在只读数据段(rodata)中
  • 初始化的全局变量和静态局部变量放在数据段(data)中

BSS段比较特殊,未初始化的全局变量和静态变量都会放置到bss段中,但因为这些变量的值都是0,没有必要再开辟空间存储,所以在可执行文件中bss段是不占用空间的。

但是BSS段的大小、起始地址、各个变量的地址信息都会分别保存在section header table和符号表symtab中,当程序运行的时候,加载器会根据这些信息在内存中紧挨着数据段之后的空间,为BSS段开辟一片存储空间,为各个变量分配存储空间。

总而言之:BSS段在可执行文件中不占用空间,在程序运行的时候才分配对应的空间

如果在编译时开启了调试选项,则可执行文件中还会有 .debug section,用来保存可执行文件中每一条二进制指令对应的源码位置信息,根据这些信息,GDB调试器就可以支持源码级的单步调试。

在最后环节,编译器还会在可执行文件中添加一些其它的section,比如 .init section,这些代码来自C语言运行库的一些汇编代码,用来初始化C程序所依赖的环境。

参考资料

以上是关于C语言程序是如何执行的的主要内容,如果未能解决你的问题,请参考以下文章

如何通过命令行简单的执行C程序

Linux中,运行一个C语言程序如何运行

C语言本身是用什么语言写的?世界上第一个能执行的编译器是如何编译?

无标C语言本身是用什么语言写的?世界上第一个能执行的编译器是如何编译?

如何在Unix 下运行c语言?

C语言调用CMD名后如何获取执行结果