2020/3/22 接着

2020/3/22+2020/3/24

C语言

C语言(gcc)编译过程

源文件hello.c

  • 预处理 hello.i(预处理文件)

  • 编译 hello.s(汇编文件)

  • 汇编 hello.o(目标文件)

  • 链接 hello.exe(可执行文件)

预处理

  • 参数:-E

  • 生成的文件: xxx.i预处理文件

  • 使用命令:gcc-E xxx.c -o xxx.i

  • 工具:预处理器(包含在gcc编译集合工具中)

  • 完成的工作:

    • 头文件展开。

      • 展开<stdio.h>文件内容,和源码一起,放到xxx.i文件中。
      • 不检查语法错误,可以在这个阶段展开任意文件。
      • 测试命令:gcc -E hello.c -o hello.i -I(大i)。(当前目录)
    • 宏定义的替换。

      • 将宏名,替换为宏值。
      • 【解释】:define PI 3.14
        • define 创建宏
        • PI:宏名
        • 3.14:宏值
    • 替换注释。

      • 把单行、多行注释替换成空行
    • 展开条件编译。

      • ifdef 宏名······endif(如果定义“宏名”,进入条件)

      • 根据条件展开代码

      • #include<stdio.h>
        #define PI 3.14
        int main()
        {
        	//展开条件编译。
        	#ifdef PI
        		printf("5555\n");
        	#endif
         } 
        

编译

  • 参数:-S

  • 生成的文件: xxx.s预处理文件

  • 使用命令:gcc -S xxx.i -o xxx.s

  • 工具:编译器(包含在gcc编译集合工具中)

  • 完成的工作:

    • 逐行检查语法错误!【重点】——编译过程整个gcc编译4步骤最耗时的部分
    • 将C语言程序翻译成汇编指令,生成汇编文件

汇编

  • 参数:-c

  • 生成的文件: xxx.o 目标文件(二进制)

  • 使用命令:gcc -c xxx.s -o xxx.o

  • 工具:汇编器(包含在gcc编译集合工具中)

  • 完成的工作:

    • 翻译:将汇编指令翻译成对应的二进制指令

链接

  • 参数:无(-o不是链接阶段参数,是用来指定文件名)

  • 生成的文件: xxx.exe 可执行文件(二进制)

  • 使用命令:gcc -c xxx.o -o xxx.exe

  • 工具:链接器(包含在gcc编译集合工具中)

  • 完成的工作:

    • 库引入。
    • 合并多目标文件。
    • 合并启动例程。

printf函数的格式化输出

d   以十进制形式输出带符号整数(正数不输出符号)
o   以八进制形式输出无符号整数(不输出前缀0)
x,X 以十六进制形式输出无符号整数(不输出前缀Ox)
u   以十进制形式输出无符号整数
f   以小数形式输出单、双精度实数
e,E 以指数形式输出单、双精度实数
g,G 以%f或%e中较短的输出宽度输出单、双精度实数
c   输出单个字符
s   输出字符串

程序调试

  • 前提:程序,没有语法问题。

    • 检查:程序出现的逻辑错误
  • 核心思想:

    • 让程序一行一行地执行
  • VS添加行号:

    • 工具——选项——文本编辑器——代码语言——行号
  • 程序调试流程:

    • 添加断点:可以添加多个。

      • 鼠标点击行号左侧灰色区域
      • F9快捷键
    • 调试,必须在Debug模式下。Release模式无效。

    • F5启动调试。

    • 断点停止位置还未执行代码

    • 开始调试

      • 逐语句执行。逐语句执行下一行(F11):遇见函数,进入自定义函数内部,逐条跟踪执行。
      • 逐过程执行。逐过程执行下一行(F10):遇见函数,不进入函数内部,逐条跟踪执行。
      • 逐断点执行。代码中有多个断点,直接跳转到下一个断点。——点击“继续”
      • 跳出函数。跳出当前函数。(shift+F10)

变量

变量3要素:

  • 变量名:用来程序中使用
  • 变量类型:开辟内存空间大小
  • 变量值:储存的实际数据

变量定义

  • 定义语法:类型名 变量名 = 变量值(一般定义法)(int m=666)

  • 会开辟内存空间给变量。变量声明不会开辟内存空间。

变量声明

  • 语法:

    • int a; 没有变量值的定义,叫做声明。
    • extern int a;添加 extern 关键字
  • 特性:

    • 变量必须有定义。
    • 编译器,在使用变量之前,必须看到变量定义。如果没有看到,编译器会自动找寻一个变量声明。提升成 定义。
    • 如果变量声明前,添加了extern关键字,无法提升!

常量

  • 不会变化、不能被修改的数据
    • define PI 3.14 ——【宏定义】定义常量
    • const int a = 10 : const关键字:只读变量

标识符

变量和常量的总称

硬性要求

  • 标识符不能是关键字、函数名。
  • 标识符只能由字母、数字、下划线组成。
  • 不能以数字开头。
  • 大小写严格区分。
    • 通常使用大写定义常量。
    • 通常使用小写定义变量。

命名规范

  • 大驼峰法:int HelloWorld;多个单词组成变量名,每个单词首字母大写。
  • 小驼峰法:int helloworld;多个单词组成变量名,每个单词首字母小写。
  • 小写+下划线(C语言专用)

sizeof关键字

  • sizeof不是函数
  • 使用方法:
    • sizeof(变量名) ——返回变量大小,单位整数字节。
    • sizeof(类型名) ——返回数据类型大小,单位整数字节。
    • sizeof(变量名) ——语法C语言支持改写法,不推荐使用。

整型

有符号整型:

整型名 名称 格式匹配符 占用的大小 最小值 最大值
int 整型 %d 4字节 -2147483648 2147483647
short 短整型 %hd 2字节 -65536 65535
long 长整型 %ld Windows:32/64位 :4字节 Linux:32位:4字节 64位:8字节 -2147483648 2147483647
long long 长长整型 %lld 8字节 -9223372036854775808 9223372036854775807

无符号类型:

整型名 名称 格式匹配符 占用的大小 最小值 最大值
unsigned int 无符号整型 %d 4字节 2147483647*2+1
unsigned short 无符号短整型 %hd 2字节 0 65535*2+1
unsigned long 无符号长整型 %ld Windows:32/64位 :4字节 Linux:32位:4字节 64位:8字节 0 2147483647*2+1
unsigned long long 无符号长长整型 %lld 8字节 0 9223372036854775807*2+1

char类型

  • 字符型

  • 单位:一个字节(8 bit 位)。

  • 格式匹配符:

    • 有符号:%hhd
    • 无符号:%hhu
  • 取值范围:

    • 有符号:-128 ~ 127
    • 无符号:0 ~ 255
#include <stdio.h>
#include <limits.h>
int main()
{
    //获取无符号数取值范围
    printf("char 无符号 min = 0, max = %hhu\n",UCHAR_MAX);
    //获取有符号数取值范围
    printf("char 无符号 min = %hhd, max = %hhd\n",CHAR_MIN,CHAR_MAX);
    //获取 char 占用的字节数
    printf("char 大小 = %u\n",sizeof(char));
    //获取 usigned char 占用的字节数
    printf("unsigned char 大小 = %u\n",sizeof(unsigned char));
    
    return 0;
}
  • ANSII码

  • 转义字符

    • ‘ \ ’:转义字符

    • ' / ':转义字符

      • 将普通字符转化为特殊意义。‘ \n ’、'\t'。
      • 将特殊字符,还原成本身意义。

实型(浮点型)【了解】

基础信息

  • 显示小数
  • float:单精度浮点型。 %f 大小:4字节。(可以用sizeof( )求取)【】
    • float x = 4.35:4.35被默认为double类型
    • float x = 4.35f:4.35被默认为float类型
  • double:双精度浮点型。 %lf 大小:8字节。

取值范围

#include <stdio.h>
#include <float.h>
int main()
{
    printf("float 范围:%f ~ %f\n",FLT_MIN,FLT_MAX);
    printf("double 范围:%lf ~ %lf\n",DBL_MIN,DBL_MAX);
}

精度问题

  • float类型:

    • 精度6 ~ 7位
      • 整数部分+小数部分<=6位,准确;
      • 整数部分+小数部分==7位,不一定准确;
      • 整数部分+小数部分>7位,不准确。
  • double类型:

    • 精度15 ~ 16位
      • 整数部分+小数部分<=15位,准确;
      • 整数部分+小数部分==16位,不一定准确;
      • 整数部分+小数部分 > 16位,不准确。
  • 不同平台(操作系统),对应float、double类型实现的精度有可能不同。以上是Windows下的特性。

  • float 和 double 不存在无符号类型。

bool类型

  • C语言原来没有bool类型。C99新增bool类型,C++自带bool类型。

  • 用处:

    • 表示:

      • 好、坏

      • 真、假

      • 对、错

      • 是、否

    • 取值:

      • true——真——1
      • false——假——0
  • C语言使用bool的条件:

    • 编译器需要支持C99的标准
    • 导入头文件"stdbool.h"
  • bool类型的大小。

    • 1字节。 sizeof()求取
  • bool没有专用的格式匹配符。打印时,使用%d来打印。

    • true——真——1
    • false——假——0

编码和存储

无符号数

unsigned int a = 12;//占用4字节,32个bit位存储
空间:00000000 00000000 00000000 00000000
存储:00000000 00000000 00000000 00001100
    
unsigned short b = 15;//占用2字节,16个bit位存储
空间:00000000 00000000
存储:00000000 00001111

有符号存储

  • 需要拿出一个二进制位,专门存储符号。标识正、负。

    • 选用最高位为符号位。
    • 正:0
    • 负:1
  • 有符号正数:

    //采用“源码存储”
    int a = 5;
    空间:0 0000000 00000000 00000000 00000000
    存储:0 0000000 00000000 00000000 00000101
    
  • 有符号负数:

    • 有符号的负数,采用“补码存储”
      • 源码:数值的二进制直接存储
      • 反码:符号位不变,将其余数值取反
      • 补码:反码+1
int b = -33;
空间:0 0000000 00000000 00000000 00000000
源码:1 0000000 00000000 00000000 00100001
反码:1 1111111 11111111 11111111 11011110
补码:1 1111111 11111111 11111111 11011111
  • 小结:

    • int——4字节——32 bit位

      • 有符号:31个数值位。取值范围-2147483648 ~ +2147483647
      • 无符号:32个数值位。取值范围0 ~ 4294967295
    • short——2字节——16bit位

      • 有符号:15个数值位。
      • 无符号:16个数值位。
  • 因此,知道数据类型占用的内存的大小,就能算出该类型无符号位、有符号位对应的取值范围。

posted @ 2020-03-22 21:56  刘凌斌  阅读(105)  评论(0编辑  收藏  举报