第一个C语言程序

244 阅读3分钟
# include <stdio.h>
# include <stdlib.h>
int main(){
    printf(" Hello Word\n");
    system("ls");
    return 0;
}

程序解释

include

#include 的意思是头文件包含,#include<stdio.h> 代表包含了stdio.h这个头文件, 使用C语言库函数需要提前包含对应的头文件,因为上面的代码使用了printf()函数,需要包含stdio.h头文件

如果想要查看printf函数所需要的哪些头文件 可以使用指令 man 3 printf查看

@ZBMAC-C02F30VXMD6M include % man 3 printf

#include<> 和#include""的区别

  • <>表示系统直接按照系统指定的目录检索
  • “” 表示系统先在“”指定的路径(没有写路径表示当前路径)查找头文件,如果找不到,再按照系统指定的目录检索

系统头文件在操作系统的位置

linux操作系统下

@ZBMAC-C02F30VXMD6M include % cd /usr/include/
@ZBMAC-C02F30VXMD6M include % ls -l | grep stdio.h
-rw-r--r--    7 root  wheel   16208  1  9  2021 stdio.h

macOS操作系统下

@ZBMAC-C02F30VXMD6M include % cd /Applications/Xcode.app/contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
@ZBMAC-C02F30VXMD6M include % ls -l | grep stdio.h
-rw-r--r--    7 root  wheel   16208  1  9  2021 stdio.h

macOS 上的头文件、库文件都被 XCode 接管了,也就是说不安装 XCode 很多开发都是做不了的。

system函数

system函数是运行程序中执行另外一个外部的程序,参数是可执行程序的名字

这个函数必须包含头文件 stdlib.h

如上面的代码 就是在打印Hello Word 之后 执行了 ls的程序,相当于把当前目录下的所有文件都打印出来 打印的结果如下

hello
hello.c
hello.dSYM
 Hello Word

程序编译

C代码编译成为可执行程序需要4个步骤

  • 预处理
    • 包括宏定义展开,头文件展开,条件编译,同时将代码中的注释删除,在这一步不会检查语法
  • 编译
    • 这一步主要是检查语法,将预处理后文件编译生成汇编文件
  • 汇编
    • 将汇编文件生成目标文件(二进制文件)
  • 链接
    • C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中

gcc

gcc(GNU Compiler Collection,GNU编译器套件),是由GNU开发的编程语言编译器,gcc原来作为GNU操作系统的官方编译器,现已被大多数类Unix操作系统(Linux,BSD, MacOS)采纳为标准的编译器,当然了,gcc 同样也适用于Windows

编译命令格式

gcc [option1] ... <filename>

g++ [option1] ... <filename>

  • 命令,选项和源文件之间使用空格分隔
  • 一行命令中可以有零个,一个或多个选项
  • 文件名可以包含文件的绝对路径,也可以使用相对路径
  • 如果命令中不包含输出可执行文件的文件名,可执行文件的文件名会自动生成一个默认名,Linux平台为a.out,Windows平台为a.exe
常用的选项
选项含义
-o file指定生成的输出文件名为file
-E只进行预处理
-S(大写)只进行预处理和编译
-c(小写)只进行预处理,编译和汇编
文件后缀
文件后缀含义
.cc语言文件
.i预处理后的c语言文件
.s编译后的汇编文件
.o编译后目标文件

预处理

gcc -E hello.c -o hello.i

该指令生成了预处理后的文件hello.i 打开hello.i 可以发现有1000多行,加了很多东西,这是预先需要的文件和路径以及条件编译都给添加了进来

编译

gcc -S hello.i -o hello.s

这一步是将预处理文件编译成了汇编文件,生成的都是相关的汇编指令,因为涉及的文件比较小 可以粘贴出来

	.section	__TEXT,__text,regular,pure_instructions
	.build_version macos, 10, 15	sdk_version 10, 15, 6
	.globl	_main                   ## -- Begin function main
	.p2align	4, 0x90
_main:                                  ## @main
	.cfi_startproc
## %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset %rbp, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register %rbp
	subq	$16, %rsp
	movl	$0, -4(%rbp)
	leaq	L_.str(%rip), %rdi
	movb	$0, %al
	callq	_printf
	leaq	L_.str.1(%rip), %rdi
	movl	%eax, -8(%rbp)          ## 4-byte Spill
	callq	_system
	xorl	%ecx, %ecx
	movl	%eax, -12(%rbp)         ## 4-byte Spill
	movl	%ecx, %eax
	addq	$16, %rsp
	popq	%rbp
	retq
	.cfi_endproc
                                        ## -- End function
	.section	__TEXT,__cstring,cstring_literals
L_.str:                                 ## @.str
	.asciz	" Hello Word\n"

L_.str.1:                               ## @.str.1
	.asciz	"ls"

.subsections_via_symbols

汇编

gcc -c hello.s -o hello.o

这一步骤是将汇编文件生成二进制文件

链接

gcc hello.o -o helloword 这一步骤是将二进制文件生成了可执行文件,