main函数种类
main函数标准类型
- 无参
int main(void) {return 0;}
- 有参
int main(int argc,char *argv[]){return 0;}
main函数其他类型
void main(int argc,char *argv[]);
void main(void);
int main();
int main(void);
非标准写法,IDE会自动调整为标准写法,但是建议使用上面的有参与无参的标准写法
GCC编译四步骤
每个步骤都可以转换。例如
预处理文件转换成汇编就可以直接gcc -c xxx.i -o xxx.o
汇编文件转换成链接可以直接gcc xxx.s -o xxx.exe
预处理
-
参数 -E
-
生成的文件:xxx.i 预处理文件
-
使用命令:gcc -E xxx.c - o xxx.i (mac使用clang命令为 cc -E xxx.c -o xxx.i)
-
工具:预处理器(包含在gcc编译集合工具中)
-
完成的工作
-
头文件展开。
- 展开stdio.h文件内容和源码一起放到xxx.i文件中
- 不检查语法错误!可以在此阶段展开任意文件。
- 使用方法:gcc -E hello.c -o hello.i -I.(大写的i,代表指定目录,‘.’代表当前目录,也就是指定当前所在目录,需要加载其他文件时才需要-I.来指定文件路径)
-
宏定义替换
-
将宏定义名,替换成宏定义值
-
#define PI 3.14【解释】:define:创建宏。 PI:宏名 3.14:宏值
-
#include<stdio.h> #define PI 3.14 //定义宏 int main(){ printf("hello.c"); printf("PI = %f\n",PI); //%f匹配符,会匹配PI的值 returm 0; } 会输出hello.c和PI =3.140000
-
-
替换注释
- 把注释替换成空行
-
展开条件编译
- 根据条件来展开代码
#include<stdio.h> //#define PI 3.14 //定义宏 int main(){ //使用宏 printf("PI = %f\n",PI); //使用条件编译 含义是如果定义了PI,那么就打印------定义了PI,否则不打印 #ifdef PI printf("----------------------定义了PI"); #endif returm 0; } 输出:如果不将define PI 3.14 注释掉 就会打印----------------------定义了PI,否则就不打印
-
编译
- 参数 :-s
- 生成的文件:xxx.s 汇编文件
- 使用命令:gcc -S xxx.i -o xxx.s
- 工具:编译器(包含在gcc编译集合工具中)
- 完成的工作
- 逐行检查语法错误。【重点】四个步骤中最耗时的
- 将c程序翻译成汇编。得到.s汇编文件
汇编
- 参数:-c
- 生成的文件:xxx.o 二进制目标文件(二进制,无法查看,打开.o查看的是将字符转换成16进制后的)
- 使用的命令:gcc -c xxx.s -o xxx.o
- 工具:汇编器(包含在gcc编译集合工具中)
- 完成的工作
- 将汇编文件翻译成对应的二进制指令
链接
- 参数:无
- 生成的文件:xxx.exe可执行文件(二进制,无法直接查看)(exe是win系统,其他系统可以自定义后缀名)
- 工具:链接器(包含在gcc编译集合工具中)
- 完成的工作
- 库引入
- 合并多目标文件
- 合并启动例程(启动例程调用main函数)
printf的格式化输出
#include<stdio.h>
#define PI 3.14
int main2(void) {
int i = 10;
printf("%d\n", i); //%d:格式匹配符,匹配整数
printf("PI = %f\n", PI); //%f:格式匹配符,匹配浮点数 PI在引号中,代表普通字符,原样输出
printf("i = %d\n", i);
printf("PI + I = %f\n", PI+i); //+ =在“”中,代表普通字符,原样输出
}
程序调试
- 前提:程序没有语法错误 -------语法错误由IDE(clion、vs)帮助检查
- 检查逻辑错误(没有达到预期的效果)
- 核心思想
- 让程序一行一行执行
程序调试流程
-
添加断点(vs行号前)
- 点击行号前灰色区域,再次点击取消
- 快捷键为F9
-
调试,必须在debug模式下,release模式无效
-
F5启动调试
-
断点的位置是尚未执行的
-
开始调试
-
逐语句执行。逐语句执行下一行(vs快捷键F11)遇见函数,进入自定义函数内部,逐条跟踪执行
-
逐过程执行。逐过程主席ing下一行(vs快捷键F10)遇见函数,不进入函数内部,逐条跟踪运行(若遇见的函数内部有断点,则会进入函数逐条执行)
-
逐断点执行。代码中有多断点,直接跳转到下一个断点。----点击继续,无快捷键。
-
跳出函数。跳出当点断点所在的函数。快捷键shift+F10
-
变量
变量3要素
- 变量名:用来在程序中使用
- 变量类型:开辟内存空间大小
- 变量值:存储实际的数据
变量的定义
- 定义语法:类型名 变量名 = 变量值(一般定义方法)。 例:int i = 99
- 会开辟内存空间给变量,变量声明不会开辟内存空间。
变量声明:
-
语法:
- int a; 没有变量值的变量定义,叫做声明。
- extern int a: 添加extern关键字
-
特性:
-
变量想要使用必须要有定义,如果没有定义。
-
编译器在使用变量之前,必须要看到变量定义,如果没有看到,编译器会自动寻找一个变量声明,提升成定义。
-
如果变量声明前,添加了extern关键字,无法提升成定义。
-
#include<stdio.h> int main(void) { // // int a = 10; //定义了变量a // a = 56; //在使用变量,给变量a赋值。 // // // int a; //变量a声明 // a = 22; //使用变量。此时无定义,编译器自动提升上暖白的声明为定义。 // int a = 40; //变量a定义 此时会报错,提示重新定义,因为前面编译器将a = 22提升成了定义 extern int z; //变量a声明 z = 44; //使用变量,此时编译器会提升声明为定义,但是int a前有extern,不能提升,所以会报错 // 提示未定义符号z Undefined symbols printf("a = %d\n",z); //使用变量 }
-
常量
不会变化,不能修改的数据。
-
”hello“、‘a’、57、-10、3.1415(浮点常量)
-
#define PI 3.1415926 -------【宏定义】语法:#define 宏名 宏值 -----强调:没有;结束标记 最常用的常量声明方式
-
const int a = 10;
-
const 关键字:被该关键字修饰的变量,表示为只读变量。
-
// // Created by Lollipop on 2020/3/23. // #include<stdio.h> #define PI 3.14 //定义常量 int main(void){ // PI = 22; // 会报错 :PI已经宏定义了,是一个常量,无法赋值 // 圆的周长 :s = PI * r *r // 圆的面积 : L = 2 * PI * r int r = 3; //变量的定义 float s = PI * r * r; float l = 2 * PI * r; printf("圆的周长:%f,\n面积:%5.2f",l,s); //周长-----%f:18.840000 %.2f:18.84 %f默认保留6位小数,%.2f保留2位小数,对第三位四舍五入 //面积-----%10.3f 28.260 10表示小数点前与小数点后一共保留5位,小数点本身算一位,超过10位正常输出。 // 3表示小数点后保留3位,如果不够10位,则用0补齐,这里会显示空 }
-
标识符
- 变量和常量的总称
硬性要求
- 标识符不能是关键字、函数名。system、printf、int、main、return。。。。。。
- 只能有字母、数字、下划线组成a-z A-Z 0-9($美元符号也可以,不出错,但是官方不允许)
- abc_s / abc_2 / _abc a_b_c_d
- 不能以数字开头。
- 大小写严格区分。
- 通常使用大写来定义常量。 #define MAX 100
- 通常使用小写来定义变量。
命名规范
- 大驼峰法:int HelloWorldHahaHohoHehe = 10;
- 多个单词组成变量名,每个单词首字母大写
- 小驼峰法:int helloWorldHahaHehe =10 ;
- 多个单词组成变量名,首个单词的首字母小写,其余每个单词首字母大写
- 小写+下划线:int hello_world_haha_hehe_hoho = 10 ;
- c语言专用!
sizeof关键字
- sizeof不是函数
- 作用:求取变量、数据类型占用的内存空间大小。
- 使用方法:
- sizeof(变量名) -------返回变量大小,单位整数字节
- sizeof(类型名)----------返回数据类型大小,单位整数字节
- sizeof 变量名---------语法C语言支持该写法,不推荐使用
整型
有符号整型
-
获取数据类型的最小值、最大值可以使用limits.h
-
// // Created by Lollipop on 2020/3/23. // #include<stdio.h> #include<limits.h> int main(void) { printf("int 大小 = %lu\n", sizeof(int)); printf("short 大小 = %lu\n", sizeof(short)); printf("long 大小 = %lu\n", sizeof(long)); printf("long long 大小 = %lu\n", sizeof(long long)); // 查看数据类型的最小值与最大值 printf("int最小值:%d,最大值:%d\n",INT_MIN,INT_MAX); printf("short最小值:%hd,最大值:%hd\n",SHRT_MIN,SHRT_MAX); printf("long最小值:%ld,最大值:%ld\n",LONG_MIN,LONG_MAX); printf("long long 最小值:%lld,最大值:%lld\n",LONG_LONG_MIN,LONG_LONG_MAX); }
整型名 | 名称 | 格式匹配符 | 占用的大小 | 最小值 | 最大值 |
---|---|---|---|---|---|
int | 整形 | %d | 4字节 | -2147483648 | 2147483647 |
short | 短整型 | %hd | 2字节 | -32768 | 32767 |
long | 长整型 | %ld | windows 32/64:8字节 linux 32(mac os):4字节 linux 64(Mac OS):8字节 | windows:-2147483647 Mac OS 64:-9223372036854775808 | windows:2147483647 Mac OS 64:-9223372036854775808 |
long long | 长长整形 | %lld | 8字节 | -9223372036854775808 | 92233720 36854775807 |
无符号整型
- 获取数据类型的最小值、最大值可以使用limits.h
整型名 | 名称 | 格式匹配符 | 占用的大小 | 最小值 | 最大值 |
---|---|---|---|---|---|
unsigned int | 无符号整形 | %u | 4字节 | 0 | 2147483647 |
unsigned short | 无符号短整型 | %hu | 2字节 | 0 | 32767 |
unsigned long | 无符号长整型 | %lu | windows 32/64:8字节 linux 32(mac os):4字节 linux 64(Mac OS):8字节 | 0 | windows:2147483647 Mac OS 64:-9223372036854775808 |
unsigned long long | 无符号长长整形 | %llu | 8字节 | 0 | 9223372036854775807 |