20160123.CCPP详解体系(0002天)
程序片段(01):字符.c
内容概要: 转义字符
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
//01.getchar();&putchar();成对使用:
// (1).使用方式分析:
// getchar();获取(命令行|控制台|屏幕->文件->网页)单个字符
// putchar();输出(命令韩|控制台|屏幕->文件->网页)单个字符
// (2).使用注意事项:
// 1).getchar();只要接受到一个字符就立即停止获取
// getchar();函数并没有形式参数,直接调用,直接返回值
// 2).putchar();和printf();一样,不会输出自动输出换行符,但是
// puts();会自动输出换行符
// 3).putchar();打印的是单个字符,单个字符采用单引号''标识
int main01(void)
{
char ch = getchar();//获取一个字符
putchar(ch);//输出一个字符
//printf("");
//puts("");
system("pause");
return 1;
}
//02.两种让命令行窗口等待的方式:
// (1).getchar();等待
// 没有提示,只要一旦感测到单个字母,立即吸收单个字符并且返回,
// 而且立即结束等待模式
// (2).system("pause");等待
// 具有提示,提示信息为"请按任意键退出.."
//03.在这里的字符吸收特点:
// scanf();吸收了单个整数
// getchar();吸收了单个字符'\r'-->'\r\n'
// 图形化特点吸收,图形化特点打印
//04.将应用程序的执行结果导入到文件的特点:
// 导入的结果为程序生成的结果,而不是用户输入程序的结果
int main02(void)
{
int num = 0;
scanf("%d", &num);
getchar();//回车算一个字符,吸收一个回车字符
//getchar();//吸收一个字符
system("pause");
return 1;
}
//04.字符'\a'是一个警告音:
// (1).警告音不可过快的发出,否则无效
// (2).具体的警告音由操作系统以及用户设置有关
// (3).时间间隔执行采用线程睡眠函数Sleep();单位是毫秒(ms)
// 加上循环结构可以实现规律间隔的执行某段儿操作
int main03(void)
{
while (-1)//0与非0
{
putchar('\a');//发声音
Sleep(1000);
}
system("pause");
return 1;
}
int main04(void)
{
printf("锄禾日当午, \n吴伟来跳舞! \n");
system("pause");
return 1;
}
//05.采用系统函数system();执行系统当中的应用程序时候:
// 需要注意是否是(x86)标识的文件夹,如果是(x86)标识的文件夹
// 那么说明该操作系统是x64位的操作系统,因此路径(x86)前面应当
// 填充一个空格,否则不能正常的执行某个程序
int main05(void)
{
system("D:\\ProgramFiles\\KuGou\\KGMusic\\KuGou.exe");
system("pause");
return 1;
}
//06. 空字符:
// (1).空字符-->'\0'|''|' '-->同属于是不可见字符
// 但是'\0'|' '打印效果为一个空格
// ''打印效果没有空格-->putchar();不能这么写-->至少得是一个空字符
// (2).'0'-->不是空字符-->属于可见字符
int main06(void)
{
//putchar('\0');//空字符,没有打印效果
//putchar('');-->不能这么写,编译报错,至少得是一个空字符
putchar(' ');//空字符-->putchar('\0');|putchar(' ');效果一致
putchar('0');
system("pause");
return 1;
}
//07.putchar();输出字符特点分析:
// (1).进制字符:
// '\???'-->字符的ASCII码值(八进制)-->实际字符
// '\x???'-->字符的ASCII码值(十六进制)-->实际字符
// (2).特殊字符的ASCII码值:
// '0'-->48
// 'A'-->65
// 'a'-->97
// (3).单个大小写英文字母的转换方式
// 大写转小写:
// 大写+32
// 小写转大写:
// 小写-32
int main07(void)
{
putchar('\101');//\101-->表示八进制的101-->1*8^0+0*8^1+1*8^2=65
putchar('\x42');//\x42-->表示十六进制的42-->2*16^0+4*16^1=66
//'0'-->48
//'A'-->67
//'a'-->97
system("pause");
return 1;
}
程序片段(02):data.c
内容概要:变量内存原理
#include <stdio.h>
int main01(void)
{
int a = 10;
printf("%p \n", &a);//查看变量a的内存地址
printf("%d", a);
system("pause");
return 1;
}
//01.变量表的概念:
// (1).在声明变量之前的时候,系统会为应用程序建立一张变量表
// (2).所有在应用程序当中声明的变量都会被注册到变量表当中
// (3).凡是需要使用到变量的时候,都会去变量表当中查找该变量
// 如果该变量被注册了,并且初始化了,则可以进行使用,否则不行
// 如果没有被初始化,将会读取到一个被编译器赋予默认垃圾值的数据
// 操作系统默认情况之下是不会自动清空内容当中的垃圾数据的
// 编译器检测到为初始化的变量,就会为变量赋予一个编译器指定的垃圾值
// 负号(-)表示垃圾,数值过大表示异常数据
// 如果该变量没有被注册,也就不能使用,编译报错
int main02(void)
{
int a, b, c;//建立变量表,管理所有的变量
//不能引用未曾声明的变量,也就是变量表当中的变量
//printf("%d \n", d);
system("pause");
return 1;
}
//02.在寄存器当中所执行的操作:
// (1).常量的生成:
// 1).这里的常量不是const常量(常变量),本质还是变量,表象为常量,处于内存当中
// 2).该常量处于代码区的符号表当中,生成流程为
// (1.CPU读取代码区符号表当中的常量
// (2.在CPU的寄存器当中生成该常量
// (2).所有的运算操作
// (3).所有的赋值操作
int main03(void)
{
int a = 1;
int b = 2;
int c;
printf("a = %p, b = %p, c = %p", &a, &b, &c);
c = a + b;
system("pause");
return 1;
}
//03.赋值操作的特点:
// (1).赋值的对象必须是变量(C语言)
// 汇编语言的赋值对象可以是寄存器
// (2).变量都是处于在内存当中,也就是所谓的操作内存
int main04(void)
{
int a = 3;//初始化:第一次的赋值操作,只能给变量进行赋值操作,变量处于内存当中
//a + 1 = 4;//a+1处于寄存器当中,C语言没有操作权限,汇编语言具备操作权限
int b = 0;
printf("%p", &b);
b = a + 1;
b = a + 2;
system("pause");
return 1;
}
//03.所有的常量使用特点:
// (1).所有的常量起源于代码区当中的符号表
// (2).生成于CPU的寄存器当中
// (3).C语言不具备操作寄存器的特权,所有无法采用取地址符进行操作
// C语言当中可以采用内嵌汇编技术
int main05(void)
{
int a;
printf("%p \n", &a);
//变量赋值,都是在寄存器当中的完成
//a = 10;//代码区当中的常量符号表10,100
//printf("%p", &10);//10这个常量在被操作的时候,其实是出于在寄存器当中
//由于C语言不具备操作寄存器的特权,所以取地址符无法进行操作
//汇编语言解释特点:
__asm
{
mov eax, 10//将代码区符号表当中的常量移植到寄存器当中
mov a, eax//在寄存器当中完成赋值操作,用于将寄存器当中的常量赋值给内存当中的变量
}
printf("a = %d \n", a);
__asm
{
mov eax, a//将内存当中变量a的数据读取到CPU的寄存器当中
add eax, 5//将寄存器当中读取到的数据与从代码区符号表当中移植进寄存器的数据进行加法操作
mov a, eax//将寄存器当中进行加法操作之后的最终数据赋值给内存当中的变量a
}
printf("a = %d \n", a);
system("pause");
return 1;
}
程序片段(03):定义变量.c
内容概要:定义变量
#include <stdlib.h>
//01.VC编译器支持采用中文作为标识符
// 但是只支持字符串形式的中文
void 锄禾日当午(){}
//02.C语言当中的标识符命名规范:
// 1.标识符的组成元素:
// 下划线("_")+数字+字母(大小写)
// 2.标识符命名法则:
// (1).见名知其意
// (2).不能以数字作为开头
// (3).不能是关键字本身(但可以有关键字组成)
// (4).遵循软件工程规范
int main(void)
{
int a;
const int data;
//int void
int main;//建议不要和函数名重名
int new;//C语言当中允许使用,但是C++当中不允许
int _ad;
int c;
int C;//大小写不同
int _;
int __;
int ___;
//标识符当中的特殊字符只有下划线("_")
//int !a;
char charnum;
int intnum;
int a1;
double a2;
char a3;//遵循软件工程规范,一看就懂
int 从前有一个很恶心的面试官搞的我痛不欲生 = 5;//VC支持中文,但是只支持字符串的中文
system("pause");
return 1;
}
程序片段(04):main.c
内容概要:变量为何一定要初始化
#include <stdio.h>
#include <stdlib.h>
//01.变量为何一定要初始化?
// 1.使用未初始化的变量特点:
// (1).声明变量的含义:
// 1).软件程序向操作系统申请内存使用权限
// 2).操作系统为软件程序赋予内存使用权限
// (2).操作系统只会负责内存使用权限的分配
// 操作系统不会对内存数据进行清理
// 编译器会检测是否对变量进行初始化,如果
// 没有进行初始化,那么分编译器特点:
// VC6.0会赋予一个垃圾数值(负的很大值),定值
// VS2015会赋予一些随机值,不定值
// (3).所谓的内存释放特点:
// 并不是清空内存当中的数据,而是软件程序
// 将对某块儿内存的使用权限回交给操作系统
// 2.不进行初始化,就会使用到前期程序使用内存之后
// 遗留下来的垃圾值,或者编译器指定的垃圾值
int main01(void)
{
int num;
num += 1;
//error C4700: 使用了为初始化的局部变量 “num”
//新老编译器,新编译器提示错误,老版本不会进行提示
//垃圾数据
system("pause");
return 1;
}
程序片段(05):main.c
内容概要:变量初始化注意事项
#include <stdio.h>
#include <stdlib.h>
//01.未初始化的变量特点:
// 1.C语言老版本的编译器会编译通过
// 2.GCC如果没有开启C++11支持,会编译通过
// 3.VC2010之前的版本,会编译通过
int main(void)
{
int a = 10;//C语言,老版本的编译器,GCC如果没有开启C++11支持,VC2010之前的版本
printf("Hello World!!! \n");
int c = 10;
return 0;
}
void go()
{
int a, b, c;//C语言定义变量
int a1;
int b1;
int c1;
int a2 = 10;
int a3 = 10, b3 = 20, c3 = 40;
}
程序片段(06):常量.c
内容概要:常量
#include <stdio.h>
#include <stdlib.h>
//01.常量内容解析:
// 1.常量深度解剖:
// 宏常量(#define)是真正意义上的常量
// 由于其不具备变量层意义,所以一旦定义就不可修改
// 常变量(const)不是真正意义上的常量
// 常变量内部具有变量的含义,加上const
// 只能限制直接意义上的赋值,而不能限制间接意义上的赋值
// 2.注意地址类型的区别:
// (1).常量地址和变量地址的特点
// (2).内容的可修改性
// 常量地址所指向的变量不可进行修改
// 变量地址所指向的变量可以进行修改
int main01(void)
{
const int 吴伟的颜值 = 99;
//吴伟的颜值 = 67;不能直接进行修改
printf("%d \n", 吴伟的颜值);
printf("%p \n", &吴伟的颜值);
//星号(*)用于根据地址取出指针指向的变量内容
//(const int *)常量地址类型转化为变量地址类型
//方可根据该地址所指向的变量当中的数据
*(int *)(&吴伟的颜值) = 98;//不算真正意义上的常量
printf("%d \n", 吴伟的颜值);
system("pause");
return 1;
}
//02.宏常量内容分析:
// 1.所有预编译指令(井号"#"作为开头的指令),都没有分号作为使用结尾
// 2.宏常量的使用特点:
// (1).真正意义上的常量
// (2).修改特点:
// 只有在源头上面进行宏常量的修改
// 后期既不能直接修改宏常量也不能间接修改变宏常量
// (3).软件可拓展性的进行使用
// 3.编程语言的使用特点:
// C语言操作硬件的级别只能到达内存一级
// 汇编语言操作硬件的级别可以达到寄存器一级
#define 吴伟的颜值 98
//define不能加分号(";"),加了就会被一起作为整体进行替换
//意义明确,实现批量修改,软件可拓展一点
int main02(void)
{
printf("%d \n", 吴伟的颜值);
//吴伟的颜值 = 100;//对宏常量进行再次赋值,直接报错
//真正意义上的常量,一次赋值,永远不能直接赋值,也不能间接赋值
// 只能从源头进行赋值操作
//C语言能操作内存,不能操作寄存器
//汇编语言同时干两个活儿
system("pause");
return 1;
}
void go()
{
printf("%d \n", 吴伟的颜值);
}
程序片段(07):变量交换.c
内容概要:变量交换
#include <stdio.h>
#include <stdlib.h>
int main01(void)
{
int a = 10;
int b = 5;
printf("a = %d, b = %d \n", a, b);
/*
//01.这种方式不行:
// 原因:数据在第一次赋值的时候,就已经发生了数据丢失
// 变量a的数据完全丢失了,找不回来了,当时有效数据只有变量b
a = b;
b = a;
*/
//02.采用水桶原理进行变量数据交换:
// 时空复杂度评析:
// temp让空间复杂度+1
// 三次赋值操作让时间+3
// 缺点:
// 1.数据容易越界
// 2.非位运算,效率低下
int temp = a;//temp=10,a=10,b=5
a = b;//a=5,b=5,temp=10;
b = temp;//a=5,b=10
//03.复杂方式,采用a+b记住变量数据原理:
// 缺点:容易导致数据越界,非位运算效率低下
a = a + b;
b = a - b;
a = a - b;
//04.最佳方式采用位运算(位移或):
// 优点:
// 1.位运算效率高
// 2.不会出现数据越界
// 3.没有增加额外的空间复杂度
a = a ^ b;
b = a ^ b;
a = a ^ b;
//05.变量数据交换总结:
// (+ - * /)会导致数据越界,最安全的做法是采用异或
printf("a = %d, b = %d \n", a, b);
system("pause");
return 1;
}
程序片段(08):进制.c
内容概要:进制
#include <stdio.h>
#include <stdlib.h>
//01.整数常量的进制表现形式:
// 默认:十进制
// 0开头:八进制
// 0x|0X开头:十六进制
//02.任何进制形式表现的整数
// 的组成元素不能超过其进制数
int main01(void)
{
int num = 012;//整数前缀0代表该整数是八进制形式的整数
//任何进制,不允许出现大于或等于进制数的数字
int num = 0x12;//整数前缀0x代表该整数是十六进制形式的整数
printf("%d \n", num);
printf("%p \n", &num);
system("pause");
return 1;
}
程序片段(09):go.c
内容概要:printf();函数解析
#include <stdio.h>
#include <stdlib.h>
//理解语法规则,逻辑严密进行
int main01(void)
{
float fl = 10.9;
//printf("%d \n", fl);
//printf();函数不会按格式控制符指定的形式进行类型转换
//%d格式控制符表示按照整数的形式解析内存中的二进制数据
system("pause");
return 1;
}
int main02(void)
{
int num = 10;
printf("%f \n", num);//实数打印
system("pause");
return 1;
}
//printf();函数总结:
// 1.理解语法规则,逻辑严密进行
// 2.printf();函数不会按照输出格式控制符所指定的数据形式进行类型转换
// 不要主观认为这是由于数据类型转换导致的结果
// 3.所谓的输出格式控制符只不过是将内存当中的固定二进制格式数据
// 给按照指定的格式进行数据解析
程序片段(10):二进制.c+sizeof.c
内容概要:数据类型解析
///二进制.c
#include<stdio.h>
#include<stdlib.h>
void main1()
{
int num = -1;
printf("%p", &num);
getchar();
}
///sizeof.c
#include <stdio.h>
#include <stdlib.h>
//01.数据类型详解:
// 1.数据类型决定:
// (1).内存容器的宽度
// (2).数据解析方式
// 例如:负整数-->补码;实数-->阶码
// 2.内存当中的二进制数据
// 需要按照指定的方式进行解析,得到相应的解析结果
int main01(void)
{
printf("%d \n", sizeof(char));
printf("%d \n", sizeof(int));
printf("%d \n", sizeof(double));
//数据类型差别,大小不一样,解析方式不一样
//10010101001
printf("%d \n", sizeof("123"));//4-->\0
printf("%d \n", sizeof('A'));//1-->VS2015居然它瞄的是4,居然当成整数进行字节数的求取
int num = 10;
printf("%d \n", sizeof(num));//1
system("pause");
return 1;
}
程序片段(11):整数.c
内容概要:int数据类型
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>//整型数据的极限头文件
//01.求取整数的范围:
// 1.头文件:#include <limits.h>
// 2.宏指令(XXX_MIN|XXX_MAX)
int main01(void)
{
int num_min = INT_MIN;
int num_max = INT_MAX;//数据的计算必须处于极限范围之内
printf("num_min = %d, num_max = %d \n", num_min, num_max);
system("pause");
return 1;
}
//02.数据溢出现象解释:
// 1.将整数化解为二进制的表现形式,
// 2.进行按照指定字节数的截断操作
int main02(void)
{
/*
1111 1111
+ 1
10000 0000
--------------
10000 0000
//截取一个字节之后是
0000 0000-->结果为0
*/
unsigned char chnum = 255 + 1;//8-->2^8=256-->0~255
printf("吴伟有%d个女友! \n", chnum);
system("pause");
return 1;
}
//03.整数和实数的二进制表示特点:
// 1.存储原理不同
// 整数采用补码形式存储
// 实数采用阶码形式存储
// 2.最高位表示符号位相同:
// 0代表正数
// 1代表负数
int main03(void)
{
char ch = -1;//1111 1111-->减一:1111 1110-->取反:0000 0001-->符号位:1000 00001
char chx = 3;//0000 0011
printf("%p, %p", &ch, &chx);
//整数,实数,第一位0代表正数,1代表负数
system("pause");
return 1;
}
程序片段(12):int.c
内容概要:数据在内存排列
#include <stdio.h>
#include <stdlib.h>
//01.整数的二进制解析:
// 1.整数在内存以二进制图形化的形式体现
// 2.二进制数据的排列规律:
// 电脑,手机:
// 低位在字节(节约内存的存储)
// 存储单位优化
// 服务器Unix:
// 低位在高字节(寻址效率的不同)
// 寻址速度提升(先找数据类型单元,再进行数据匹配动作)
int main01(void)
{
int num = 1;
printf("%p \n", &num);
//0000 0000 0000 0000 0000 0000 0000 0001
//001
//002
//0000 0000
//0000 0000
//0000 0000
//0000 0001
//0000 0001
//0000 0000
//0000 0000
//0000 0000
//01//1000 0000 01
//02//0000 0000 00
//03//0000 0000 00
//04//0000 0000 00
//0000 0001
//低位在低字节,高位在高字节
//电脑,手机,低位在低字节,高位在高字节
//服务器Unix低位在高字节
system("pause");
return 1;
}
程序片段(13):run.c
内容概要:补码
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
//01.负数不能采用无符号类型的变量进行存储:
// 1.会造成数据被解析的过大
// 2.无符号类型的变量只能存储正数
// 负数的二进制通常很大,因为以1作为开头
// 所以存储的时候不能用无符号进行存储
// 否则存储的数据实体过大
int main01(void)
{
unsigned int num = -1;//1111 1111 1111 1111 1111 1111 1111 1111
printf("%u", num);
for (int i = 0; i < num; i++)
{//循环10次
printf("你好天朝! \n");
}
system("pause");
return 1;
}
//02.计算机当中的整数存储原理:
// 1.所有的整数都采用补码存储
// 2.原码-->反码-->补码:
// 正整数的原码,反码,补码一致
// 负整数的原码,反码,补码特点:
// 原码:该负数所对应的正整数的原码最高位加符号位(1)
// 反码:该负数所对应的原码的符号位不变,其余为取反
// 补码:该负数所对应的反码+1
// 3.采用补码的优点:
// 提升运算效率,减少不必要的计算操作
// 将以前的多步骤运算进行精简
// 例如:统一了+-法的差异,全部采用加法,符号位转到补码的表示当中
// 举例:1-1-2-2<==>1+(-1)+(-2)+(-3)-->统一为加法运算法则
int main02(void)
{
char ch = -17;//计算机都是补码存储,手机,电脑,服务器也同样采用补码进行整数的存储
//0001 0001 +17的原码
//1001 0001 -17的原码
//1111 1110 -17的反码
//1111 1111 -17的补码 EF-->十六进制
printf("%p \n", &ch);
system("pause");
return 1;
}
//03.有符号和无符号的推理法则:
// 1.-1所对应的内存二进制数据是:
// 1111 1111 1111 1111 1111 1111 1111 1111
// 2.对内存二进制数据的解析方式:
// %d:按照有符号的解析法则(负数倒推)
// 补码-->反码-->原码-->负数
// 例如:-1的补码
// 1111 1111 补码
// 1111 1110 反码
// 1000 0001 原码-->就是-1
// %u:按照无符号的解析法则(整数倒推)
// 补码=原码-->证书
// 1111 1111-->就是255
int main03(void)
{
int num = -1;
//0000 0000 0000 0000 0000 0000 0000 0001 +1原码
//1000 0000 0000 0000 0000 0000 0000 0001 - 1原码
//1111 1111 1111 1111 1111 1111 1111 1110 - 1反码
//1111 1111 1111 1111 1111 1111 1111 1111 - 1补码
printf("%d \n", num);
printf("%u \n", num);
system("pause");
return 1;
}
int main04(void)
{
printf("INT_MIN = %d, INT_MAX = %d \n", INT_MIN, INT_MAX);
system("pause");
return 1;
}
//04.特殊数据的二进制数值:
// -1的内存二进制数据全是1
// 按照有符号解析得出-1
// 按照无符号解析就是一个整数最大值
// 越界现象解释:
// 物极必反的二进制数据转换特点
int main05(void)
{
int num = -1;
unsigned int data = 42949697295u;//无符号数据 1111 1111 1111 1111 1111 1111 1111 1111全部的是数据,并且按照正整数的方式进行解析
int num1 = 4294967295u;//等价于32个二进制的1
unsigned int data1 = -1;//等价于32个二进制的1
printf("%d \n", num);//-1
printf("%u \n", num);//4294967295
printf("%d \n", num1);//-1
printf("%u \n", num1);//4294967295
printf("%u \n", data);//4294967295
printf("%d \n", data);//-1
printf("%u \n", data1);//4294967295
printf("%d \n", data1);//-1
printf("%f \n", 1);//printf,不管三七二十一,抓区二进制数据就解析
system("pause");
return 1;
}
int main06(void)
{
printf("INT_MIN = %d, INT_MAX = %d \n", INT_MIN, INT_MAX);
printf("INT_MIN = %d, INT_MAX + 1 = %d \n", INT_MIN, INT_MAX + 1);
printf("INT_MIN - 1 = %d, INT_MAX = %d \n", INT_MIN - 1, INT_MAX);
printf("UINT_MIN = %d, UINT_MAX = %d \n", 0, UINT_MAX);
printf("UINT_MIN = %d, UINT_MAX + 1 = %d \n", 0, UINT_MAX + 1);
printf("UINT_MIN - 1 =%d, UINT_MAX = %d \n", 0 - 1, UINT_MAX);
system("pause");
return 1;
}