文章目录
一、解决提示窗一闪而过:
1. 通过 system()函数解决:
在 return 0;之前 添加 system("pause"); 函数调用。
2. 借助VS工具解决:
在项目上 ---》右键 ---》 属性 ---》 配置属性 ---》 连接器 ---》 系统 ---》 子系统
---》 在下拉框中选择“控制台 (/SUBSYSTEM:CONSOLE)”
二、两种编写 helloworld 的方式:
1. 借助VS编辑工具编写。
创建项目 --》 创建 helloworld.c 源文件 --》 写 helloworld程序 --》Ctrl + F5 执行。
2. 借助记事本、gcc编译工具编写。
gcc编译工具的环境变量配置:
在QT的安装目录中找 gcc.exe 目录位置。例如: C:\Qt\Qt5.5.0\Tools\mingw492_32\bin
我的电脑 --》属性 --》 高级系统设置 --》 环境变量 --》系统环境变量 --》 path --》 将gcc.exe 目录位置写入到 path的值中。
使用记事本创建 helloworld.c 文件 ——》 在记事本中写 helloworld 程序
--》 使用gcc编译工具 ,在记事本写的 helloworld.c 所在目录中,执行 gcc helloworld.c -o myhello.exe
--》 在终端(黑窗口)中,运行 : myhello.exe
单行注释://
多行注释:/* 注释内容 */
不允许嵌套使用。 多行中可嵌套单行。
三、system 函数:
执行系统命令。如: pause、cmd、calc、mspaint、notepad.....
system("cmd"); system("calc");
清屏命令:cls; system("cls");
四、gcc编译4步骤:【重点】
首先简单处理一下,然后翻译。
1. 预处理文件
gcc -E xxx.c -o xxx.i,-o 是将 xxx.c 文件生成的文件重名为 xxx.i;或者说xxx.c 文件输出的文件为 xxx.i。
1.1 预处理做的工作为:
1)头文件展开。 --- 不检查语法错误。 可以展开任意文件。
2)宏定义替换。 --- 将宏名替换为宏值。
3)替换注释。 --- 变成空行
4)展开条件编译 --- 根据条件来展开指令。
1.2 头文件展开,可以展开任意文件
预处理会将包含进来的头文件展开,可以展开任意文件。这个文件可以是自己定义的,也可以是系统的库文件。
(1)先新建一个文件,文件名为MyselfFW.h,文件的内容为:
hhhhh
1111
112222
(2)在 helloworld.cpp 文件里面包含 MyselfFW.h
(3)用 gcc -E helloworld.cpp -o helloworld.i,预处理 helloworld.cpp 文件,得到 helloworld.i 文件。然后打开 helloworld.i 查看。
1.3 宏定义替换
预处理会将程序中的宏名替换为宏值。
(1)在程序中定义一个宏:PI 3.14
(2)使用 gcc -E helloworld.cpp -o helloworld.i 预处理 ,再次查看 helloworld.i 文件。PI 被替换为了 3.14:
1.4 替换注释
预处理会将程序中的注释替交换为空行。
(1)在程序中写几行注释:
(2)使用 gcc -E helloworld.cpp -o helloworld.i 预处理 ,再次查看 helloworld.i 文件。注释被替换为了空行:
1.5 展开条件编译 — 根据条件来展开指令
预处理会根据条件来展开指令。
(1)在程序中,写一个条件编译,意思就是如果定义了 PI ,那么在程序中就出现 #ifdef … #endif 中的内容。#endif 是条件编译内容的结束标志
#include <stdio.h>
#include "/oracle/heima/CBasics/day01/MyselfFW.h"
#define PI 3.14
int main()
{
#ifdef PI
printf("PI=%lf\n",PI);
#endif
printf("helloworld.\n");
return 0;
}
(2)使用 gcc -E helloworld.cpp -o helloworld.i 预处理 ,再次查看 helloworld.i 文件。printf("PI=%lf\n",PI);
在程序中出现了:
(3)将 #define PI 3.14
注释掉,然后使用 gcc -E helloworld.cpp -o helloworld.i 预处理 ,再次查看 helloworld.i 文件。printf("PI=%lf\n",PI);
没有在程序中出现:
2.编译 -S xxx.s 汇编文件
gcc -S hello.i -o hello.s
1)逐行检查语法错误,就相当于翻译,肯定要检查语法错误的。【重点】 --- 整个编译4步骤中最耗时的过程。
2)将C程序翻译成汇编指令,得到.s 汇编文件。
2.1 逐行检查,检查语法错误
我们把 PI 的宏定义去掉,但是程序中也使用 PI ,这是错误的。
//#define PI 3.14
int main()
{
printf("PI=%lf\n",PI);
printf("helloworld.\n");
return 0;
}
(1)我们故意写错,依旧预处理程序,gcc -E helloworld.c -o helloworld.i。
(2)然后将预处理好程序进行编译,就会报错。gcc -S helloworld.i -o helloworld.s。如果编译出错,是不会生成 helloworld.s 文件以及后面的目标文件的。
2.2 将C程序翻译成汇编指令
将程序修改回来,正常进行预处理,然后进行编译。gcc -S helloworld.i -o helloworld.s。就将C程序翻译成了汇编指令:
3.汇编 -c xxx.o 目标文件
gcc -c hello.s -o hello.o
1)翻译:将汇编指令翻译成对应的二进制编码。
(1)执行汇编,将汇编指令翻译成对应的二进制编码,生成 helloworld.o 文件
(2)查看 helloworld.o 文件:出现乱码,打开的方式错误。
4. 链接 xxx.exe 可执行文件。
Windows下:gcc hello.o -o hello.exe
Linux 下: gcc hello.o -o hello;不用.exe
1)数据段合并
2)数据地址回填
3)库引入
五、VS调试程序:
添加行号:
工具--》选项 --》文本编辑器--》C/C++ --》行号 选中。
1. 设置断点。F5启动调试
2. 停止的位置,是尚未执行的指令。
3. 逐语句执行一下条 (F11):进入函数内部,逐条执行跟踪。
3. 逐过程执行一下条 (F10):不进入函数内部,逐条执行程序。
4. 添加监视:
调试 --》窗口 --》监视:输入监视变量名。自动监视变量值的变化。
六、CPU内部结构与寄存器
6.1 64位和32位系统区别
寄存器是CPU内部最基本的存储单元
CPU对外是通过总线(地址、控制、数据)来和外部设备交互的,总线的宽度是8位,同 时CPU的寄存器也是8位,那么这个CPU就叫8位CPU
如果总线是32位,寄存器也是32位的,那么这个CPU就是32位CPU
有一种CPU内部的寄存器是32位的,但总线是16位,准32为CPU
所有的64位CPU兼容32位的指令,32位要兼容16位的指令,所以在64位的CPU上是 可以识别32位的指令
在64位的CPU构架上运行了64位的软件操作系统,那么这个系统是64位
在64位的CPU构架上,运行了32位的软件操作系统,那么这个系统就是32位
64位的软件不能运行在32位的CPU之上
6.2 寄存器、缓存、内存三者关系
按与CPU远近来分,离得最近的是寄存器,然后缓存(CPU缓存),最后内存。
CPU计算时,先预先把要用的数据从硬盘读到内存,然后再把即将要用的数据读到寄存器。于是 CPU<--->寄存器<--->内存,这就是它们之间的信息交换。
那为什么有缓存呢?因为如果经常操作内存中的同一址地的数据,就会影响速度。于是就在寄存器与内存之间设置一个缓存。
从缓存提取的速度远高于内存。当然缓存的价格肯定远远高于内存,不然的话,机器里就没有内存的存在。
由此可以看出,从远近来看:CPU—>寄存器—> 缓存 —> 内存。