C语言基础
一、C语言概念
语言:编译型(需要编译运行),解释型(如python,可直接运行)
机器语言00 d8,汇编语言mov ax,00FFH,高级语言
起源:
CPL语言–>BCPL语言–>B语言(UNIX) -->C语言(D.M.Ritchie:C语言之父)
标准:
1978:标准C -->1983:ANSI C -->1990:C90 -->1999:C99
特点:
- 面向过程的语言
- 结构化的程序设计语言:采用自顶向下的规划、结构化的编程、模块化的设计
- 功能强大:既是一种高级语言,同时也提供丰富的低级操作,适用于开发应用软件和系统软件
- 移植性好:适应各种不同型号机器或各类操作系统
- 标准函数库、代码和数据的分离
开发流程:
分析问题,编写程序(.c),编译(.o),链接(ELF可执行和链接的格式),调试运行
二、GCC解释器
- 发展:起源于GNU(非洲牛羚)项目,又称革奴计划,Richard Stallman在1983年创办。GCC是GNU开发出来的一款编译器软件,全名为GNU CC。
- 作用:GCC符合ANSI C标准,能够编译C,C++,Object C等语言编写的程序。将高级语言翻译成机器语言。
- 语法结构:
gcc [options] [filenames]
options:
- 常用选项:
-std=<standard> Assume that the input sources are for <standard>.指定C语言的标准,如C99
-B <directory> Add <directory> to the compiler's search paths.
-v Display the programs invoked by the compiler.查看当前gcc版本
-E Preprocess(预编译) only; do not compile, assemble or link.
-S Compile only; do not assemble or link.生成汇编代码
-c Compile(编译) and assemble(汇编), but do not link.生成目标文件“.o”,不链接执行文件
-o <file> Place the output into <file>.生成目标文件“.o”并链接执行文件,注意“.o”文件会在执行文件生成后自动删去
-g 在可执行程序中包含标准调试信息
-l dir 在头文件的搜索路径列表中添加dir目录
- 优化选项:
数字越大代表优化等级越高,程序运行速度越快,常用 -O2
-O :减小代码的长度和执行时间
-O2 : 在-O基础上进行额外调整,如处理器指令调度
-O3 : 在-O2基础上进行额外调整,如循环展开等
- 警告和出错选项:
警告:warning ,语法出错:error
“-Wall”最常用
-ansi : 支持符合ANSI标准的C程序
-pedantic : 允许发出ANSI C标准所列出的全部警告信息
-pedantic-error : 允许发出ANSI C标准所列出的全部错误信息
-w : 关闭所有警告
-Wall : 允许发出gcc所提供的所有有用的报警信息
- 制作库文件选项:
-I dir :在库文件的搜索路径列表中添加dir目录
-static :链接静态库
-lname :链接名为name的库文件
-shared :表明是使用共享库
-
文件结构
src:存放C源文件
bin: 存放二进制文件,即可执行文件
obj: 存放 “.o” 目标文件
include: 放置自己定义的 “.h” 头文件 -
实例
使用gcc输出:
gcc hello.c #默认在目录下生成一个.out文件
gcc -o bin/hello hello.c #编译hello.c,输出.o目标文件到bin目录下,并链接执行文件
#或者
gcc -o obj/hello.o -c src/hello.c
gcc -o bin/hello obj/hello.o
./bin/hallo #执行
三、GDB调试器(Debugger)
- 概念:是GNU开源组织发布的强大的Unix/Linux下的程序调试工具,可与微软的VC等工具媲美
gdb debug测试,设置断点-单步运行-检查错误 - 作用:
- 启动用户程序后,可以按照用户的需求随意运行程序;
- 可让被调试程序在用户所设定的断点处停住;
- 当程序被停住时,可以检查此时用户程序中所发生的事;
- 可动态改变用户程序的执行环境。
- 语法
注意:
(1)gdb进行调试的是可执行文件而不是源代码
(2)对“.c”源文件进行编译一定要加上“-g”,这样编译出的可执行文件才包含调试信息
gcc -g [其他选项] [文件名]
gdb [可执行文件]
#进入调试界面
#(gdb) 调试命令:
display /i $pc 调试输出汇编码信息
q(quit):退出调试
l(list):查看所载入文件内容,从代码第一行开始10行左右,或者指定行,显示指定行上下10行信息
b(break):设置断点,程序运行到断点停止,b后面加行号或者函数名,显示最后执行行的下一行
info b :查看设置断点情况
r(run):默认从第一行开始运行代码,在r后面加行号可从指定行开始运行
p(print) n: 查看变量n的值
n(next):单步运行下一行代码(遇到函数不会进入函数)
s(step):单步运行下一行代码(遇到函数会进入函数)
c(continue):回复程序运行,执行剩余的程序
四、基本数据类型
-
常量和变量:注意变量在函数中可以只声明不定义,系统自动赋值随机数
-
数据类型分类: 基本数据类型,构造数据类型,指针类型,空类型
命名法:驼峰命名法,匈牙利命名法 -
基础数据类型:
-
整型:
- 概念:整型数据在内存中的存放形式是以补码表示的
- 反码:正数的反码与原码一致;负数的反码是对原码按位取反,只是最高位(符号位)不变。
- 补码:正数的补码和原码相同;负数的补码:负数的反码加1,可以用 模减去该数的绝对值 来获得负数的补码。
- 模:单字节(8位)运算的模为256=2^8
如-5的补码为:-5=256-5=251=(1111 1011)b
- 一个整型变量的存储单元占据4个字节
- 分类:无符号就是没有第一位符号位,以下是一个32位机的整型分类:
- 概念:整型数据在内存中的存放形式是以补码表示的
名称 | 全称类型说明符 | 所写类型说明符 | 位数 | 范围 |
---|---|---|---|---|
整型 | [signed]int | int | 32 | |
无符号整型 | unsigned int | unsigned | 32 | |
短整型 | [signed]short int | short | 16 | |
无符号短整型 | unsigned short int | unsigned short | 16 | |
长整型 | [signed]long int | long | 32 | |
无符号长整型 | unsigned long int | unsigned long | 32 |
整型和长整型区别:int型和编译器的版本有关系,在tc等16位编译器下,他的范围是-32768至32767之间,只有在vc++等32位编译器下才是-2147483648至2147483648。而long不管在16位还是32位编译器取值都是-2147483648至2147483648。
特别64位机中:
long long的最大值:9223372036854775807(2^63-1)
long long的最小值:-9223372036854775808 (-264)-0=-264
unsigned long long的最大值:18446744073709551615(2^64-1)
-
整型常量:
- 十进制表示:不以0开头(0开头为8进制),负数前加“-”,后缀"l""L"表示长整型 123L,“u”"U"表示无符号数 123LU
- 八进制表示:以0开头的一个连续数字字列,序列中只能有0~7
- 十六进制表示:以0x或0X开头的一个连续数字和字母序列
-
字符型:
-
概念:字符型用于存储字符,对应ASCII编码的二进制形式你存储,占用1个字节。ASCII = American Standard Code for Information Interchange
-
C语言把字符型看作一种特别短的整数类型,允许参与算术运算。
- 有符号字符型表示的数值范围-128~127,类型说明符[signed] char
- 无符号字符型表示的数值范围 0~255,类型说明符unsigned char
- ‘a’-32=‘A’, ‘A’+32=‘c’
-
//输出ascii码常用符号
#include<stdio.h>
int main()
{
int i=32;
for(;i<127;++i)
{
printf("%c",i);
if(i%10==0)printf("\n");
}
printf("\n");
return 0;
}
-
字符常量:用单引号’ '括起来的一个字符。只能用单引号,单个字符。
- 转义字符:一种特殊字符常量,以反斜线 \ 开头,后跟一个或几个字符。转义字符具有特定含义。
printf("\'iotek\' is from \"shanghai\"\n");
printf("xh\tname\tage\taddress\n");
printf("10\tjack\t20\tshanghai\n");
- 字符变量:用来存储字符常量,即单个字符。char a,b;
每个字符变量被分配一个字节的内存空间,因此只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元之中的。
可以把字符看成是整型。C语言允许对整型变量赋予字符值,也允许对字符值变量赋予整型值,值的意义为字符对应ASCII码。
char c1='b';
char c2='\055'; //'-'
char c3='\x6f'; //'o'
char c4=97; //'a'
- 字符串型:字符串常量是由一对双引号括起的字符序列。
C语言中没有相应的字符串变量,但是可以用一个字符数组来存放一个字符串常量。
char str[]="Hello";
printf("str:%s\n",str);
printf("size:%d\n",sizeof(str)); //size:6
字符串常量占内存字节数等于字符串中字节数加1.增加的一个字节中存放字符“\0”(ASCII为0),这是字符串结束的标志。
-
浮点型
- 概念:也称实型,表示实数。只采用十进制。浮点数不可以做取余运算。
- 分类:
- 实型常量分为两种形式:小数形式1.1、指数形式(科学计数法)2.3E5L=2.3*105(long double型)
- 变量分为
- 单精度(float):占4字节,精度6位小数
- 双精度(double):占8个字节,精度15位小数
- 长双精度(long double):占8个字节
- 变量分为
- 实型常量分为两种形式:小数形式1.1、指数形式(科学计数法)2.3E5L=2.3*105(long double型)
- 存储方式:存储方式遵循IEEE 754标准规定(美国电气和电子工程师协会IEEE二进制浮点数算术标准)。一个浮点数(32位)由符号位(1位)、阶码(8位)、尾数(23位) 组成。
- 小数转二进制:乘2取整 例5.5->101.1->1.011*22
上例在计算机中的存储:符号位为0(正数),阶码为2+127=129(指数+127)再转换为二进制=1000 0001,尾数为011加上20个0凑23位,一共32位。转换为16进制数=0x40B0 0000
所以5.5=0x40B0 0000
%f和%lf分别是float类型和double类型用于格式化输入输出时对应的格式符号。
其中:
float,单精度浮点型,对应%f。
double,双精度浮点型,对应%lf。
在用于输出时:
float类型可以使用%lf格式,但不会有任何好处。
double类型如果使用了%f格式可能会导致输出错误。
在用于输入时:
double类型使用了%f格式,会导致输入值错误。
float类型使用double类型不仅会导致输入错误,还可能引起程序崩溃。
所以在输入输出时,一定要区分好double和float,而使用对应的格式符号。
-
只读变量和常量的区别
-
只读变量:不能改变的变量
const int a=1 -
const修饰只读变量,只能读取不能被修改;
只读变量是变量,定义时需要分配内存空间。而常量是一个静态值,不需要分配内存空间。
常量能用来作为定义数组的维数,能放在case关键字后面,但是只读变量不可以。
-
-
枚举类型和枚举变量
- 枚举类型声明:
enum 枚举类型名{枚举值1,..,枚举值n};
- 枚举变量的定义:
//方式一
enum Day MON=1,TUE=2;
//方式二
enum Day{MON,TUE} MON=1,TUE=2;
//方式三
enum Day{MON=1,TUE};
//可在声明时同时赋值
enum Day{MON=1,TUE};
五、输入输出函数
包含在stdio.h(standard input/output)头文件中
- printf(): 格式输出函数,末尾 ‘f’ 表示“格式”(format)之意。
printf("非格式字符串+格式控制字符串",输出列表);
格式字符串是以%开头的字符串,可以说明输出数据的类型:
格式字符:%d十进制整数, %f浮点数, %c字符, %s字符串, %o(8进制), %x(16进制),%#x(16进制以0x输出) %u(十进制无符号整数), %e(double指数形式),%%(输出百分号%),%l(long整数)
printf("%-25.15f",a); //“-”表示靠左,若无则默认空格补全长度,“25”表示数据长度25,“.15”表示精确到15位小数
非格式字符串如“hello”,在输出时原样打印,做提示作用。
格式控制字符串和各输出项在数量和类型上应该一一对应。
%[标志][输出最小宽度][.精度][长度]类型
输出最小宽度:用十进制整数来表示输出的最少位数。整数前加上标志0表示补充0,不加默认补充空格。若输出值大于宽度,则直接输出值。
printf("%05d",10); //00010
精度:精度格式符以“.”开头,后跟十进制整数。含义:如果输出数字,则表示小数的位数;如果输出字符,则表示输出字符的个数;若实际位数大于所定义精度数,则截去超过的部分。
printf("%.2f",8.666); //8.66
长度:长度格式符分为%h(按短整型输出),%l(按长整型输出)
-
scanf(): 格式输入函数,按用户指定格式从键盘上把数据输入到指定的变量中。
返回值为输入数值个数scanf("格式控制字符串",地址列表); 格式控制字符串作用与printf函数相同,但不能显示非格式字符串 地址列表中给出各变量的地址,&变量名 %[输入宽度][长度]类型 输入宽度:用十进制整数指定,若实际输入宽度超过指定宽度,则多余部分会被截掉。 注意:要输输入类型不匹配,会造成变量不能初始化,变量被赋予随机数值 例1字符串输入: char s[20]; printf("please input a sentence:"); scanf("%s",s); //遇到空格符就会结束,无法输出句子 fgets(s,sizeof(s)-1,stdin);//可以读取标准输入 printf("s:%s\n",s); 例2陷阱:键盘->缓存->输入,第一次输入了8和回车键(为了执行命令),读取了8,但是第二次读取了缓存中的回车符号就直接输出了,这个问题可以通过使用getchar()解决 printf("please input a num:"); int num; scanf("%d",&num); printf("please input a character:"); getchar()//读取掉上一次输入时输入的回车键 char ch; scanf("%c",&ch); printf("ch:%c\n",ch); 例3输入多个字符时的空格问题: printf("please input two char:"); char ch1,ch2; scanf("%c %c",&ch1,ch2);//%c和%c之间加一个空格,输入时就可以增加空白字符 printf("ch1:%c ch2:%c\n",ch1,ch2); 判断字符输入类型正确与否: if(scanf("%d",&num)!=1) 单独返回的值为输入的合法的数据的个数: result=scanf("%d%d%d",a,b,c); //输入都合法则result=3
- "*"的使用:
```c
printf中表示替代值:
int width,precision;
float salary = 555.343f;
scanf("%d%d",&width,&precision);
printf("salary:%*.*f\n",width,precision,salary);
//第一个*[标志位]用width值代替,第二个*[.精度]由precision值代替
scanf中表示跳过:
int n;
scanf("%*d %*d %d",&n);/
/只取第三个输入值
printf("n:%d\n",n)
-
scanf注意:
- scanf函数中没有精度控制,如scanf("%5.2f",&a);是非法的
- 在输入多个数值时,若格式控制串中没有非格式字符作输入数据的间隔,则可用空格、TAB或回车作间隔。C编译时,在碰到非法数据(如输入类型不匹配的数据)时即认为该数据结束。
- 在输入字符数据时,若格式控制中无非格式字符,则认为所有输入字符均为有效字符。若格式控制中用空格隔开,则输入字符间可以使用空格、TAB或回车作间隔。
- 如果格式控制串中有非格式字符则输入时也要输入该非格式字符。
-
getchar()函数:键盘输入函数,从键盘输入一个字符就获取一个字符。通常将其赋予一个字符变量。
int 字符变量 = getchar();
-
putchar()函数:字符输出函数,屏幕终端上输出单个字符
int putchar(字符变量);
运算符和表达式
- 运算符和表达式介绍
- 概念:算数表达式,拥有优先级和结合性
- 结合性:运算,逻辑,逗号运算符–从左到右,左结合性; 条件,赋值,单目运算符–从右到左,右结合性
- 在表达式中,各运算量参与运算的先后顺序不仅要遵守运算符优先级规定,还要受运算符结合性约束。
- 分类:
-
一元(单目)运算符 。都为右结合性
-
二元(双目)运算符:优先级–算数运算符>关系运算符>逻辑运算符
-
运算符
- 算数运算符
- 作用:用于各类数值计算
- 分类:+,-,*,/,%(求余,模运算),++(自增),–(自减)
- 使用除/时,若除数被除数都是整数则商取整,若有一个小数则商取浮点数
- 余数的符号取决于被除数,除数和被除数都要求为整型
- ++(自增),–(自减)注意前缀(++i)和后缀(i++)区别。
i=j+++x; //优先使用j++,i=(j++)+x
- 算数表达式:用运算符号和括号将运算对象(或称操作数)连接起来的符合C规则的式子。
- 关系运算符
- 作用:用于比较运算
- 分类:>,<,>=,<=,==,!=
- 关系表达式:用关系运算符将运算对象(或称操作数)连接起来的符合C规则的式子。
- 逻辑运算符
- 作用:用于逻辑运算
- 分类:!, &&, ||
- 逻辑表达式:用逻辑运算符将运算对象(或称操作数)连接起来的符合C规则的式子。
int main()
{
int a,b,res;
//逻辑与&&当左边的表达式为假(为0)则不执行右边的表达式,逻辑断路
(a=6)&&(b=8);
printf("a:%d b: %d\n",a,b);//a:6 b: 8
(a=0)&&(b=9); //a=0值为零,为假,右边语句不执行
printf("a:%d b: %d\n",a,b);//a:0 b: 8
//逻辑或||当左边的表达式为真(大于0)则不执行右边的表达式,逻辑短路
(a=6)||(b=8);
printf("a:%d b: %d\n",a,b);//a:6 b: 8
(a=0)||(b=8);
printf("a:%d b: %d\n",a,b);//a:0 b: 8
res=(a=0)||(b=0);
printf("a:%d b: %d,res:%d\n",a,b,res);//a:0 b: 0,res:0
//逻辑非
res=!(a=0)||(b=11);
printf("a:%d b: %d,res:%d\n",a,b,res); //a:0 b: 0,res:1
res=!((a=0)||(b=11));
printf("a:%d b: %d,res:%d\n",a,b,res);//a:0 b: 11,res:0
}
- 逗号运算符
- 作用:用于把两个或多个表达式连接起来组成一个逗号表达式。
- 一般形式:表达式1,表达式2,…,表达式n
-运算过程为:先求表达式1的值,再求表达式2的值,依次求,最后把最右表达式的值作为整个表达式的值。x=2+3,x-4 //输出1 (x=2*5,x-3),x*4 //输出28 逗号表达式可以嵌套!
- 注意在变量定义,函数参数列表中的逗号只是用作各变量之间的间隔符。
- 位操作运算符
- 作用:参与运算的量,按二进制位进行运算。
- 分类:&(位与), |(位或), ~(位非), ^(位异或,不同输出1,相同输出0), <<(左移), >>(右移)
- 赋值运算符
- 作用:用于赋值计算
- 分类:简单赋值(=), 复合算数赋值(+=,-=,*=,/=,%=), 复合位运算赋值(&=,|=,^=,>>=,<<=,没有位非~=)
- 左值:能出现在赋值运算符左边的内容,左值意味着一个存储单元。
- 右值:能出现在赋值运算符右边的内容,右值意味着一个值。
- 一般变量可以作为左值,而表达式不能。
- 条件运算符
- 作用:一个三目运算符,用于条件求值(?😃。
char gender;
gender = (type==0)? 'm' : "f" ;
//如果type==0为真,则赋予gender='m',若条件为假,则赋予gender="f"
/*右结合性*/
max=a>b&&a>c?a: b>c?b:c;//先运算b>c?,然后运算a>b&&a>c?
- 指针运算符
- 作用:用于取内容(*),和取地址(&)两种运算。
- 求字节数运算符
- 作用:用于计算数据类型所占的字节数(sizeof)。
- 特殊运算符
-
包括括号(),下标[],成员("->“和”.")等等。
-
类型转换
- 概念:变量的数据类型是可以转换的,自动和强制转换都是一种临时性转换,不会改变数据说明时对变量定义的类型
- 类型转换分类:
-
1.自动转换(隐式转换)
- 自动转换发生在不同数据类型的量混合运算时,由编译器自动处理,最终取决于运算式中精度最高的类型
- 常用形式例:
long x = 10; //这边右值"10"是int型,自动转换成了左值long型 float i=4.6f; //这里都是float型不做转换,推荐使用 float j=4.3; //这里"4.3"默认是双精度double型,向左自动转换成float型(低精度),这种赋值容易引起精度丢失,不推荐使用 int k=20.55 //精度丢失
-
发生场合:
- 当算数表达式或逻辑表达式中的操作数类型不相同时
- 当赋值运算符右侧表达式的类型和左侧变量的类型不匹配时
- 当函数调用中的实参类型与其对应的型参类型不匹配时
- 当return语句中表达式的类型和函数返回值的类型不匹配时
-
数据类型提升
- char/short -> int ->unsigned int->long int->unsigned long int
- float -> double -> long double
- 整型 -> 浮点型
- 有符号数 -> 无符号数
-
2.强制类型转换(显式转换)
- 允许程序员使用类型转换运算符进行数据类型转换
- 形式:(类型说明符)(表达式) //必须加括号()
- 功能:把表达式的运算结果强制转换成类型说明符所表示的类型
-
-
位的操作运算符
1.左移和右移
移位类型|正数|负数
-|-|-
逻辑左移|低位补0高位丢失|低位补0高位丢失
算数左移|低位补0高位丢失|低位补0高位丢失
逻辑右移|高位补0低位丢失|高位补0低位丢失
算数右移|高位补0低位丢失|高位补1低位丢失- 移位针对整型,不可以浮点型
- 在右移中对于负数是采用逻辑还是算数右移取决于编译器(gcc采用算数右移)
int x=8,y=-8;
printf("x:%d %#x\n",x<<1,x<<1);
printf("y:%d %#x\n",y<<1,y<<1);
printf("x:%d %#x\n",x>>1,x>>1);
printf("y:%d %#x\n",y>>1,y>>1);
数组
- 数组的概念
- 数组的结构
栈 stack
概念:一种先进后出(FILO)的数据结构
- 用数组实现栈
//stack.h文件
#define MAX_SIZE 30
int is_full();
int is_empty();
void push(int element);
int popup();
int top();
//stack.c文件
#include "stack.h"
int stack[MAX_SIZE];
int position;
//滿栈
int is_full()
{
return position >= MAX_SIZE;
}
//空栈
int is_empty()
{
return position == 0;
}
//压栈:赋予指针所在格元素,然后指针增进一格
void push(int element)
{
if(is_full())
return;
stack[position++] = element;
//position++;
}
//出栈:指针退一格指向栈顶元素输出
int popup()
{
if(is_empty())
return 0;
//position--;
int element = stack[--position];
return element;
}
//获得栈顶元素:选择到指针下一格输出
int top()
{
if (is_empty())
return 0;
int element = stack[position-1];
return element;
}
//test_stack.c
#include <stdio.h>
#include "stack.h"
int main(void)
{
push(10);
push(11);
push(12);
push(13);
printf("popup is: %d\n",popup());
printf("popup is: %d\n",popup());
printf("top is: %d\n",top());
push(14);
printf("popup is: %d\n",popup());
printf("popup is: %d\n",popup());
printf("popup is: %d\n",popup());
printf("popup is: %d\n",popup());
return 0;
}
队列 queue
概念:一种先进先出(FIFO)的数据结构
-
队列只允许在后端(rear)/尾部进行插入操作,在前端(front)/头部进行删除操作。
-
用数组实现队列
//queue.h文件
#define MAX_SIZE 30
int is_full();
int is_empty();
//入列
void enqueue(int element);
//出列
int dequeue();
//queue.c文件
#include "queue.h"
int queue[MAX_SIZE];
unsigned int position;
void remove(unsigned int index);
int is_full()
{
return position >= MAX_SIZE;
}
int is_empty()
{
return position == 0;
}
//入列,从队列尾部插入数据
void enqueue(int element)
{
if(is_full())
return;
queue[position++] = element;
}
//出列,输出队列头部信息,并删除
int dequeue()
{
if(is_empty())
return;
int element = queue[0];
//创建一个删除元素的函数remove(index)
remove(0);
position--;
return element;
}
void remove(unsigned int index)
//功能:删除数组中元素。实际运用效率不高,以后可以考虑使用链表来删除元素
{
int i;
for(i=index;i<position-1;i++){//position指向尾部,元素为空
queue[i]=queue[i+1];
}
//queue[i]=0;可以清除也可以不清除尾部元素。
}
//test_queue.c
#include <stdio.h>
#include "queue.h"
int main(void)
{
enqueue(1);
enqueue(2);
enqueue(3);
printf("dequeue():%d\n",dequeue());
printf("dequeue():%d\n",dequeue());
printf("dequeue():%d\n",dequeue());
printf("dequeue():%d\n",dequeue());
return 0;
}
程序编写
- 标准:
/*
*Copyright:
*filename: hello.c
*description:
*author:
*date:
*version:
*/
#include <stdio.h>
//“#”为预处理指令,系统头文件用尖括号“< .h>”,自己的头文件用双引号“ ".h" ” stdio为标准输入输出函数,包含printf,scanf等
int main(void) //()括号内可使用任何参数,(void)说明无任何参数
{
printf("Hello\n"); //语句以“;”结尾
}
- 整数的溢出
#include <stdio.h>
int main(){
short num1=32767;
short num2=num1+1;
printf("num1:%d\t num2:%d\t\n",num1,num2);
return 0;
}
//num1:32767 num2:-32768