01.C语言 - Hello World

142 阅读7分钟

1.C语言简介

2. 一个简单的例子 hello world

#include<stdio.h>
#define PI 3.14
int main()
{
	// 安装了MinGW环境, 使用gcc编译器, 用notepad++左右视图方式打开(左视图hello.c, 右视图hello.i)   
	// 用cmd打开Dos模拟器, 执行命令 C:\>gcc -E hello.c -o hello.i 预处理文件,用另一视图打开,观察hello.i文件
	printf("hello world\n");
	printf("hello %lf\n", PI);    // 宏替换
	//printf("hello world\n")     // 预处理不会检查错误(行尾没有分号)
	
	#if 0
	printf("hello world\n");    // 此行内容不会编译, 因为0在C语言中表示false
	#endif
	
	
	#if WIN32
	printf("hello WIN32\n");
	#endif
	
	#if WIN64
	printf("hello WIN64\n");    // #if 也可用于长文注释
	#endif
	
	#if abc
	printf("hello abc\n");    // #if 条件编译 - 默认并不会编译此行,需要加"-D"参数 gcc -E hello.c -o hello.i -Dabc 如此才会编译
	#endif
    
	return 0;
}

3. GCC编译过程

C程序编译可执行程序4步:

image-20220421153928500.png

image-20220421163812295.png

  1. 预处理 hello.i

    带 "#" 的语句是预处理指令, 预处理指令在预处理阶段就进行处理了, 预处理: gcc -E hello.c -o hello.i

    • 头文件展开:#include <stdio.h>包含了stdio.h(预处理时将stdio.h文件拷贝至预处理文件中)

    • 宏替换(宏定义展开):#define代表声明一个宏, 在预处理阶段会将宏替换, 如: #define PI 3.14 会将 PI 全部替换为 3.14

    • 条件编译: 条件不成立: #if 0 ... #endif, 条件成立: #if 1 ... #endif, 条件参数(在编译时指定):#if abc ... #endif

    • 删除注释

    • 不检查语法错误

    条件编译 - #if abc ... #endif 默认并不会编译此代码块, 需加"-D"参数才会进行编译如: gcc -E hello.c -o hello.i -Dabc

  2. 编译hello.s

    检查语法, 将预处理后文件编译生成汇编文件, 编译: gcc -S hello.i -o hello.s

  3. 汇编hello.o

    将汇编文件生成目标文件(二进制文件)

  4. 链接

    设置运行环境, 堆栈等, 链接其他库 (C语言写的程序是需要依赖各种库,所以编译之后还需要把库链接到最终的可执行程序中去)

选项含义
-o file指定生成的输出文件名为file
-E只进行预处理
-S(大写)只进行预处理和编译
-c(小写)只进行预处理、编译和汇编
预处理:gcc -E hello.c -o hello.i
编  译:gcc -S hello.i -o hello.s
汇  编:gcc -c hello.s -o hello.o
链  接:gcc hello.o -o hello

4.helloworld程序解析

#include <stdio.h>    // #:关键标识符,表示引入头文件; include: 引入头文件关键字
											// stdio.h: 系统标准输入、输出库对应的头文件, 给printf()函数服务
											// #include <...>: 尖括号表示是系统库函数;		#include "...": 双引号引起来的表示是用户自定义函数
int main(void)				// int表示函数返回值类型是整数类型; main: 函数名,main函数也叫主函数 整个程序中仅且只有一个main函数,程序从main函数开始执行(程序唯一入口,必须有,且只有1个); void表示函数调用无需传参
{                     // {左大括号: 函数体起始位置
        printf("hello world\n"); // 将 "hello world" 打印到屏幕上;  \n: 转义字符, 表示回车换行  new line
  			system("pause");				 // 调用system函数, 实现暂停功能
        return 0;			// 返回当前函数调用 -- 退出程序.  0要跟main()函数的返回值 一一对应
}											// }右大括号: 函数体结束位置

5.system()函数

作用: 在程序中启动另一个程序 参数:要的是待启动程序的路径名

#include <stdio.h>
#include <stdlib.h>
int main()
{
        //syetem启动程序,如果这个程序系统可以找到,不用加路径,
        //如果环境变量找不到,需要加路径
        //windows路径以\\  或 /
        //system("mspaint");//启动画图板
        //system("C:\\Users\\Administrator\\Desktop\\c++13\\hello.exe");
        system("C:/Users/Administrator/Desktop/c++13/hello.exe");
        printf("hello worldfbahfoahfoooooooooooooooooooooo\n");//打印到终端
        return 0;
}

6.CPU内部结构与寄存器(了解)

32位CPU是32位地址总线 2^32, 最大仅支持4GB内存

2^32
2^10 * 2^10 * 2^10 * 2^2
1024 * 1024 * 1024 * 4
1k   = 1M   = 1G   = 4G

-----------------------------------------------

2^64
2^10 * 2^10 * 2^10 * 2^10 * 2^10 * 2^10 * 2^4
1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 16
1k   = 1M   = 1G   = 1T   = 1P   = 1EB  = 16EB

寄存器 缓存 cpu 内存之间的关系: cpu > 寄存器 > 缓存 > 内存

wpsA738.tmp.jpg

image-20220420163914499.png

寄存器名字

*8位**16位**32位**64位*
AAXEAXRAX
BBXEBXRBX
CCXECXRCX
DDXEDXRDX

寄存器、缓存、内存三者关系

按与CPU远近来分,离得最近的是寄存器,然后缓存(CPU缓存),最后内存。

CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。于是 CPU<--->寄存器<--->内存,这就是它们之间的信息交换。

那为什么有缓存呢?因为如果经常操作内存中的同一址地的数据,就会影响速度。于是就在寄存器与内存之间设置一个缓存。

因为从缓存提取的速度远高于内存。当然缓存的价格肯定远远高于内存,不然的话,机器里就没有内存的存在。

由此可以看出,从远近来看:CPU〈---〉寄存器〈---〉 缓存 〈---〉 内存


【扩展内容】位, 字节, 字的区别

  1. 位(bit) 二进制位, 计算机内部数据储存的最小单位, 11010100是一个8位二进制数。一个二进制位只可以表示0和1两种状态(2^1), 两个二进制位可以表示00、01、10、11四种(2^2)状态, 三位二进制数可表示八种状态(2^3)...
  2. 字节(byte) 字节来自英文Byte,习惯上用大写的“B”表示。 计算机中数据处理的基本单位。计算机中以字节为单位存储和解释信息,规定一个字节由八个二进制位构成,即1个字节等于8个比特(1Byte=8bit)。八位二进制数最小为00000000,最大为11111111;通常1个字节可以存入一个ASCII码,2个字节可以存放一个汉字国标码。
  3. **字(word)**计算机进行数据处理时,一次存取、加工和传送的数据长度称为字(word)。一个字通常由一个或多个(一般是字节的整数位)字节构成。例如286微机的字由2个字节组成,它的字长为16;486微机的字由4个字节组成,它的字长为32位机。 计算机的字长决定了其CPU一次操作处理实际位数的多少,由此可见计算机的字长越大,其性能越优越。

  一个ascll码就是一个字节, 因为ascll码的二进制范围是00000000到11111111, 十进制范围是0到255,

// 扩展内容
一、定义
1、位/比特(bit)
位/比特(bit)是计算机中最小的数据存储单位。二进制中每一位的状态只能是012、字节(byte)
字节(byte)由8位(bit)组成,是存储空间的基本计量单位,通常1个字节可以存储半个汉字或1个英文字母。

3、字(word)
字(word)是计算机进行数据存储、处理和运算的单位,由若干个字节(byte)组成。字的位数叫字长,不同处理器性能的计算机中字长不同,例如32位处理器中,1字=32位=4字节,64位处理器中,1字=64位=8字节。

二、相互转换
1B(byte,字节)= 8 bit;
1KB(Kibibyte)     = 2^10 B  = 1024 B;
1MB(Megabyte)     = 2^10 KB = 1024 KB = 2^20 B;
1GB(Gigabyte)     = 2^10 MB = 1024 MB = 2^30 B;
1TB(Terabyte)     = 2^10 GB = 1024 GB = 2^40 B;
1PB(Petabyte)     = 2^10 TB = 1024 TB = 2^50 B;
1EB(Exabyte)      = 2^10 PB = 1024 PB = 2^60 B;
1ZB(Zettabyte)    = 2^10 EB = 1024 EB = 2^70 B;
1YB(Yottabyte)    = 2^10 ZB = 1024 ZB = 2^80 B;
1BB(Brontobyte)   = 2^10 YB = 1024 YB = 2^90 B;
1NB(Nonabyte)     = 2^10 BB = 1024 BB = 2^100 B;
1DB(Doggabyte)    = 2^10 NB = 1024 NB = 2^110 B;
1CB(Corydonbyte)  = 2^10 DB = 1024 DB = 2^120 B;
1XB(Xerobyte)     = 2^10 CB = 1024 CB = 2^130 B;

详见两篇文章:

  1. ASCII
  2. 计算机编码