AaronYang风格 C语言挑讲[二][基本类型、运算符和表达式]
AaronYang风格就是:不讲老生长谈的东西,挑主题内难懂的地方细讲,其他总结一笔带过,有口诀教口诀,示例实践出来,文章内容充实。
本文原理理解性方面的较多,但是都被我用gif图片(自己photoshop做的)讲解
更底层的东西,我自己都不懂的,不可能拿出来讲的
本文是针对有学过其他编程语言的来学的,有很多地方我跳过略讲,所以这不是一篇入门的文章
我在看C的时候,其实发现了一些挺好玩的东西,比如宏替换,带符号,不带符号的类型。C的常量定义也不一样。
重点讲位运算符的运算,还有逗号运算符
最主要是每个类型占了多少个字节的理解,以后优化程序可以用到。
要避免不必要的类型转换
精彩预览:
比如课外知识,很多人知道怎么去写编程,但原理知道的很少,知道怎么用,比如操作系统32位和64位的关于编程方面的区别
这里讲的很容易理解,自己做了些图片方便理解,如果想直接看,就在本文末最后一节,呵呵
数据类型基本一览
我学C#的,无符号类型和指针没怎么接触过
其他概念:
打开程序时候,数据会存在内存中(个别可能在寄存器中),我们要对每个数据在内存中分配若干个字节,用于存放数据。数据所占用的内存字节数称为该数据的“数据长度”。所以我们要定义不同的数据类型,来安排合适的长度去分配数据存放。于是我们需要数据类型这个概念,不知道有没有听懂了
常量
(一) 整型常量
- 十进制:平常的数字写法,0,22,+11,-3
- 八进制:0开头的书写形式,例如00,+08,-033,021
- 十六进制:0x开头的书写形式,例如0x1,-0x121,+0x12,0x21
占用字节:一般微型机中占用2个字节,不分进制,他们的数值范围都是十进制的-32768~+32767
长整型常量:范围 -2147483648~+2147483647,占用4个字节。
书写形式:在整数的末尾加上 l 或者 L 例如: 10L -011L +0x15L
那么其他的都是短整型常量了。如果整型常量后面没有字母“L”或“l”,而且超过了短整型常量能够表示的数值范围,则自动认为该常量是长整型常量了,例如-32769、 32768、40000都是长整型常量了
总结: 整型常量分短整型和长整型两种,又分十进制,八进制,十六进制三种书写形式,使用时,要注意区分。例如,88和88L,数值一样,但是它们在内存中占用不同数量的字节;比如 10,010L,0x10虽然是短整型常量,但是表示的整数值不一样。
(二) 实型常量
一般形式
[+ 或者 –] 整数部分 小数点 小数部分
指数形式
[+ 或者 –] 整数部分 小数点 小数部分 e或者E [+ 或者 –] 指数(就是普通的整数)
例如 12.345e3 就等于 12.345乘以10的3次方 就是 12345
12345E-3 就等于 12345乘以10的-3次方 就是12.345
总结: 实型常量在一般的微机中占用4个字节,数值范围都是-10的38次方 到 10的38次方,有效数字是7位
例如: 1.23456789和1.234567是相同的,因为有效数字是7位,所以后两位是无效的
(三) 字符常量
就是char类型了,C语言中,字母区分大小写的,‘a’和‘A’ 是不一样的
在内存中,每个字符常量都占用一个字节,具体存放的是该字符对应的ASCII代码值。例如 ‘a’‘A’ ‘1' ‘%’ ‘\r’ ‘\x3d’在内存中的字节中存放的分别是十进制整数 97 65 49 37 13 61
总结:由于整型常量在内存中存放的是整数值,如果其值在0~127之间,C语言规定也可以将其看成一个字符型常量,就是数字当符号使用。例如:整型常量111、70、40可以当做字符常量 ‘o’ ‘F’ ‘(’ 来使用
有个好玩的例子: ‘a’+5 这里a就会被当做97使用,所以等于结果值102,在C#中我也试过了,也是如此
(四) 字符串常量
就是字符串,在C#中是string定义的
但是C中定义字符串不是用string的,以后说吧.
例如“aAbBcCdD” 转义字符 \
字符串长度
普通的不说了,说点特殊的,例如 “ ”是0, “\\ABCD\\”是6, “\101\102\x43\x44”是4
虽然每个字符在内存中只占用1个字节,但C语言规定,每个字符串在内存中占用的字节数等于字符串的长度+1,其中最后一个字节存放的字符为“空字符串”,其值为0,书写的时常用转义字符“\0”来表示,在C语言中称为字符串结束标记。例如:字符串“AB”和 “A”的长度分别是2和1,但他们在内存中分别占用3和2个字节,所以 “A”和 ‘A’是不同的,一个占用2个字节,一个占用1个字节
关于这个在C#是否是这样的,我不清楚…
(五) 符号常量 #define 符号常量 常量
C编译程序将在程序编译前将所有的符号常量自动替换成对应的常量
变量规范 名字全部用大写字母
例如 #define PI 3.1415926 效果同于C#的 const double PI=3.1415926
#define A ‘A’ 效果等同于C#的 const char A=‘A’
宏定义命令的一般格式如下: #define 宏名 一串符号
宏名就等同于变量名,那个一串符号,你可以理解为对应的值
宏替换就是 把名字替换值,然后进行处理。由于宏替换是在编译前进行的,所以宏定义命令属于C语言的”预编译命令”
基本例子,理解替换的过程
#define PI 3.14159
#define R 10
#define D (R+R)
#define L PI*D
若程序中用到了L
①先替换成 PI*D
②再将PI替换成3.14156、D替换成(R+R),结果就是3.14159*(R+R)
③这里面还有宏名,再替换R,最后结果就是 3.14159*(10+10)
下面是1个特殊的例子:
例子: #define PI 3.14159
#define R1 2+3
#define R2 (2+3)
若求 2*PI*R1的值 宏替换结果是”2*3.14159*2+3”
若求 2*PI*R2的值 宏替换结果是”2*3.14159*(2+3)”
变量
定义模式跟C#基本一样
类型 变量名=值
类型 变量名
算了,直接举例子
int i;
float i,j;
unsigned short me;
long a1=11L;
unsigned short a1=0111,a2=0x11;
int i=1,j=2,k;
int i,j,k=10;
char c1=‘A’,c2,c3=‘a’;
有名常量的定义(就是C#中的const)
在C#中用 const 类型 名称定义的,变量规范都是一样的,名字用全部的大写字母
C中如下:
const 数据类型符 变量名1=初值,变量名2=初值2 等;
跟C# const一样
例如 const char FALE='男',FEMALE='女';
一旦定义,程序运行的时候就不许修改了,否则报错
运算符(跟C#基本一样,多了几个,这里假设你已经学了其他编程语言)
运算符感觉最基本的
加 减 乘 除 求余数 + – * / %
正负号 + -
关系运算符 < > <= >= == !=
还有 就是 ! && ||
三元运算符(书中写的三元,二元都是三目,二目,我不太习惯) ? :
其他符号像 赋值= 逗号 , 数组中的[ ] 其他基本的 括号 ( ) 递增的 ++ --
运算完赋值相关的+= -= *= /= %=
数据长度运算符(sizeof),这个C#中没有
关于成员运算符,我们在C#中,都是 对象 点(.)出来对象中的属性或者方法的,C中用-> 和 . 关于->在PHP中也是用这个的
指针运算符,C#中应该没有吧(& * + – )
比较难理解的有 位运算符(例如<< >> ^ ~ & | &=等),其实C#中也有,我们很少用,过一会讲解一下这个
运算相关的还有 就是 结合性,运算的优先级 这个概念
我以前在 Javascript讲过,语言逻辑都是通用的,那里讲的比较详细 点击查看
一、基本常见的跳过了
二、长度运算符(sizeof)
打开C-Free5
sizeof 是C里面的关键字 并非函数,意思是c 所占的内存多少 单位是字节
getch(); 用此命令可以在运行的的时候,按任意键退出 ,如果没有此命令,屏幕闪一下就没了(程序结束就退出) 所以看不见结果等同于C#中的Console.ReadLine();
重点讲解一下 位运算符
编程中: 0代表false,假,1代表true,真,有句口诀,非0即真
一、位逻辑运算符
使用数目和位置 对象类型 结果类型 结合性
位非 ~ 单目前缀 整型 整型 自右向左
位与 & 双目中缀 整型 整型 自左向右
位或 | 双目中缀 整型 整型 自左向右
按位加 ^ 双目中缀 整型 整型 自左向右
关于16进制转2进制的对照表格
【例一】
设变量定义如下: unsigned short a=0111,b=0x53
先把 a 无符号八进制转换成二进制: 0000 0000 0100 1001
b 无符号十六进制转换成二进制: 0000 0000 0101 0011
①~a 把二进制是0的位置变成1,是1的变成0(对应的二进制就是1111 1111 1011 0110),然后转换成八进制为0177666,运算后a不变
②a&b,两两位对应,有0则0,对应的二进制是(0000 0000 0100 0001),然后转换成八进制为0101,运算后a不变
③a|b,两两位对应,有1则1,对应的二进制是(0000 0000 0101 1011),然后转换成八进制为0133,运算后a不变
④a^b,两两位对应,相异则1,对应的二进制是(0000 0000 0001 1010),然后转换成八进制为032,运算后a不变
二、位移位运算符
使用数目和位置 运算规则 对象类型 结果类型 结合性
左移 << 双目中缀 a<<b.a向左移b位 整型 整型 自左向右
右移 >> 双目中缀 a>>b.a向右移b位 整型 整型 自左向右
移位时,移出的位数全部丢弃,移出的空位补入的数与 左移还是右移有关
如果是左移,则规定补入的数全部是0,;如果是右移,如果不带符号,则补入的数全部是0;如果带符号,则补入的数全部等于原数的最左边位上的数(即原数的符号位)
下面假设a已经是转换成二进制的,原本本来a=47,现在转换成了二进制101111
无符号左移,带符号左移,他们两个一样的,我做张图片演示
无符号右移
带符号右移
带符号右移(最左边是0,就补0,最左边是1,就补1)移动完后,在将二进制转换成十进制,这就是位移位运算符
三、位自反赋值运算符
功能类似常用的 += -=,运算完了,改变原有的值
主要是这5个: &= |= ^= <<= >>=
这里不讲了,就是经过位移运算后,改变原有的值,第一部分,第二部分讲的都是运算后不改变原有的值
表达式(跟C#90%一样)
- 算数表达式
- 关系表达式
- 逻辑表达式
- 赋值表达式
- 逗号表达式
- 条件表达式
重点讲一下,C#中没有的 逗号的特殊用法,可以组成逗号表达式
逗号除了声明变量时 int a,b=10,还有函数参数也是用逗号来间隔的
但是那里的逗号都不是运算符,在C中,逗号可以是一种运算符。下面我们通过几个例子学习一下
逗号运算符,用它可以将两个表达式连接起来。如:
3+5,6+8
称为逗号表达式,又称为“顺序求值运算符”。逗号表达式的一般形式为
表达式1,表达式,表达式3……表达式n
最终的结果都是以最后一个表达式的值为准,也就是表达式n的值
例如上面一个逗号表达式的值就是6+8,也就是14
例一
这里先算3乘以5等于15,然后把值赋给了a,a等于15了,然后15乘以4,最终整个表达式的值就是60了
例二
C语言表达能力强,其中一个重要方面就在于它的表达式类型丰富,运算符功能强,因而c使用灵活,适应性强
类型转换的小例子,提醒优化(变量=表达式)
C#中有强制转换和隐式转换,C也有,自动转换规则和强制转换规则,99%和C#一样
课外知识
一个字节等于8个二进制位;即 1byte=8bit
计算机采用二进制的,8=2^3,通常最高位为符号位
二进制数系统中,每个0或1就是一个位(bit),位是数据存储的最小单位。其中8bit就称为一个字节(Byte)。计算机中的CPU位数指的是CPU一次能处理的最大位数。例如32位计算机的CPU一次最多能处理32位数据。
Bit,乃BInary digit(二进制数)位的缩写,是数学家John Wilder Tukey提议的术语(可能是1946年提出,但有资料称1943年就提出了)。这个术语第一次被正式使用,是在香农著名的《信息论》,即《通信的数学理论》(A Mathematical Theory of Communication)论文之第1页中所以说64位操作系统,每次读取的位数更多,所以处理数据更快了,但可能存在兼容性的问题
下面讲一个小题目了
回忆本篇第一部分
short类型的字节长度2
long类型长度是4
下面用图片解释一下
变量b3是4字节的,存放65536后,对应的二进制位数如下:
将b3的值赋予变量a的时候,b3的4字节中低16位数据(右边2字节)组成的新值就赋予变量a了,最后转换成十进制显示,就是0
学习总结
- 对常量,宏替换,变量 原理性的理解和使用
- 数据长度,进制转换的理解
- 位运算符的理解和使用
- 逗号运算符的使用
- 占用字节数的理解和实践