本文主要受到王建伟C++的影响,根据其C++新经典中的第二部分知识编写
非常推荐大家阅读《C++新经典》,再买一本C++工具书
适合于C基础不扎实的人阅读,从根源上了解C,从而进一步了解C++
主要从十一个方面讲解C语言,特别会指出C语言的易错点,以及楼主在刷编程题时,遇到的问题
如果有讲述不对的地方,欢迎各位大佬指正
目录
目录
前言
学好一门语言 = 好老师+自身努力+举一反三(百度+自学)
C++发展史:B语言——》C语言———》C++语言
C语言,效率高,比汇编语言(低10-20%),可以直接访问物理内存,可以写系统软件
C++ 引入类、虚函数等等
C++ 特点:封装性+继承性+多态性
市场工作需求:win(30%),linux(70%)
VS2019环境:
搭建语言环境步骤 工具——导入到导出设置——重置——否——Visual C++
第一章 数据类型、运算符、表达式
1.1常量和变量
常量: 在程序运行中,其值不能被改变的量就叫常量
变量:变量名(第一个字母表示变量类型)就是一个标识符,变量名区分大小写
整型常量 : 150;
实型常量(又叫浮点型常量): 带小数点的12.3;
字符常量: 'a' 用单引号引起来的 一个字符
printf("35+48的值是%d\n",35+46); // %d : 格式化标记,表示显示一个 十进制数
标识符:好像人的名字(张三,李四): 由字母、数字、下划线三种字符组成,并且第一个字符为字母或者下划线。比如:test,icount,myclass
保留字: 系统保留起来,有特殊的用途,所以不能将语言中的保留字作为标识符使用,否则会出现语法错误。
1.1.1整型变量
十进制数字 123;-456;
八进制数字,以0开头的数字。
012;//八进制的12
int abc;
abc = 012;//=是赋值语句,是把等号右边的值赋给等号左边的变量
printf("012的十进制数是:%d\n",abc);
十六进制数: 以0x开头的数是十六进制数
0x123; 0x12;
abc = 0x12;
printf("0x12的十进制数是:%d\n",abc);
sizeof : 是一个运算符(像+、-、*等),作用(某种类型变量在计算机内存中占多少个字节)
printf("abc这个变里占用的内存字节数是%d\n",sizeof (abe));
整型变量的定义
int a,b,c;
unsigned int d,e,f;
int k = 189; //这叫做定义变量的时候初始化
k = 678; //这叫做赋值语向
short m = 189;
//在一个常数后边加一个字母U,表示该常数用无符号整型方式存储,相当于unsigned int:
//在一个常数后边加一个字母L,表示该常数用长整型方式存储,相当于long:
//在一个常数后边加一个字母F,表示该常数用浮点方式存储,相当于float;
1.1.2 浮点型变量
十进制浮点数表示形式 :0.12 ;3.1415926
指数形式表示的浮点数:168E2/168E+2 ==> 168 *10“2 = 168*100 = 16800
168E-2 ===>168 *10“(-2) = 1.68
实型(浮点型)数据(在内存中都是以指数形式来存储)
float :单精度变量,一般提供7位有效数字(保守估计6位),这个数字随机器而异的
double:双精度变量,一般提供16位有效数字(保守估计15位),这个数字随机器而异的
float d,e,f;
double i,k;
12345.6789;
//10000.0--只有一位有效数字导致此结果 ,这就是精度问题
//12000.0--有两位有效数字导致此结果,这就是精度问题
//12300.0--有三位有效数字导致此结果,这就是精度问题
//12345.67X--有七位有效数字导致此结果,X随机分配一位
//相当于12345.6700
0.1234;
//0.1XXXXX--只有一位有效数字
//0.12XXXX--有两位有效数字导致此结果
float af2 = 0.51 //丢失了数据
这个还是很有意思的,为什么af2 = 0.51,打印出来就有问题了呢?
因为在计算机中,数字会先转换为二进制数字保存在内存中,然后再将二进制数转换为十进制数展示,而这里就会涉及到除法,就有除不尽的情况
1.1.3 字符型变量
常规字符 : 用单引号引起来的 一个 字符,'a'; '$'; 'b';
特殊字符: 转义字符,以\开头('\n'换行; '\\')
字符变量,只能保存一个字符,因为一个字符型变量在内存中只占一个字节
char c1,c2;
cl = 'a'; //实际上是把字符常量对应的ASCALL码 (数字)放到了变量所代表的内存中
//所以字符如果用%d,打印出来就是一个数字哦~
c2 = 'b';
char c1,c2.
c1 = 97;//c1 = 'a'
c2 = 98;//c2 = 'b'
printf("c1 = %c,c2 = %c",c1,c2)://%c以字符的形式输出
c2 = c2+4;
printf("c2 = %c",c2); //这个打印出来就是 f ~
1.1.4 字符串常量
字符串变量:用一对双引号引起来的一堆字符(可以是一个字符,也可以是多个字符)
“Hello world!","wangjianwei"
那么字符串变量和字符型变量究竟有什么区别呢?可以看到字符和字符串在内存中的显示
char c;
c = 'a';//字符型常量
c = "a"; //报错(2个字节不能存在一个字节中),字符串常量;
// \0 是字符串结束的标记,系统自动添加,但是printf的时候,并不输出出来
printf("abcd\0abd\n")//结果是abcd
1.1.5 变量赋值
int a = 3:
int a,b,c =6;//只给c赋值
//对于没赋值的变里,其值是不确定的,大家不能随意拿过来用。
1.2 数值型数据之间的混合运算
系统会选取在这些类型中能表达最大数字的变量,作为其他变量所转到的目标类型
见下图,举一些例子:
char+long ----->int + long ------>unsigned+long------>long
最后会输出的是long
int a = 2;
double da = 15.6;
double de = a + da ;//系统把int型转换为double,然后在和 da 进行相加
1.3 算术运算符
+(加),-(减),*(乘),/(除)
%(取余,也叫模运算符,该运算符两侧都要求为整数)
printf("表达式的结果为%d\n”,5/3); //两个整数相除,系统会舍弃小数部分
9/4 = 2 ,9%4 = 1;
1.4 运算符优先级
这个建议查表,像*优先级低于[ ],*与++优先级相同,但从右往左结合,这些都可以通过查表知道
优先级问题:先乘除 后加减,如果优先级相同,从左到右
赋值运算符 =
int i;
i= 4 + 3: //把等号右边的值赋给等号左边的变 ==> l= (4+3) //括号,
1.5 强制类型转换符
一般形式:(类型名)(表达式)
强类型转换运算符: 将一个表达式转换成所需要的类型
b = (double)a: //但是a本身类型并没有变化而是整个这个结果的类型发生变化。
int a = 10;
double b;
b = (double)a: //但是a本身类型并没有变化而是整个这个结果的类型发生变化。
(int)x + y: //只将x转换成了整型,然后和y相加。
1.6 自增自减操作符
自增和自减操作符只能用于变量,不能用于常量或者表达式。
比如错误的用法 5++, (a-b)++ ,--5,--(a+b):
i++; //7, 先用后加
++i; //7, 先加后用
i--; 先用后减
--i; 先减后用
如果i++或者++i单独写成一个语句,没有任何区别,都是将变里自身+1,没有区别
但是,如果放在函数调用中,结果就会不同。
printf(“i++的结果是= %d\n",i++): //先用后加 i++的结果是=6 ,i本身变成了7
printf(“i是= %d\n",i): //7
-i++; //实际上等价于-(i++);
i+++j; //实际上等价于(i++)+j;
c编译器在处理时会尽可能多的从左到右将若干字符组成一个运算符,但仍极度不建议这么写
1.7 赋值运算符
赋值的原则:类型要相同,类型不同时用强制转换,当用强制类型转换时,开发者必须自己明确知道不会溢出。
// 变量 = 值
int a;
a = 5;
a=6.5 //将实型数据给整型变量时,小数部分会被舍去
float f;
f = 125;//在内存中,1.25E+2 实型变量按照指数形式保存在内存中
/*……………………………………*/
char a: //这个叫变量定义,系统会给a分配一个字节的内存,内存里边的值不确定
char a = 90://这个叫变量定义 ,同时给变量赋初值(定义时初始化)
//这个不是赋值,这个叫 定义时赋初值。
char范围 -128------127
a=900; //赋值语句,这会造成溢出。溢出后a里面的内容就变得不可预料
复合的赋值运算符:在赋值运算符 = 之前加上其他运算符,构成了复合的赋值运算符
注意:复合的赋值运算符的两个运算符之间必须紧换着不能用空格分开
a += 3 ===> a = a+3
int x = 2,y=8;
x*= y+8; // 等价于 x = x*(y+8);
//如果 *= 右侧是个表达式的话,则相当于该表达式有括号
int a, b, c;
a = b = c = 5; //c=5,b=5,a=5,从右到左赋值顺序,不熟直接上括号
1.8 逗号运算符和逗号表达式
格式 : 表达式1,表达式2
求解顺序: 先算表达式1,然后算表达式2;最终结果是表达式2的值
a = (4,5);// a=5;
a = 3*5,a*4 //15
result=(a = 3*5,a*4) //60
逗号表达式的扩展形式:
表达式1,表达式2,表达式3,.....表达式N,最终的值是表达式N的值