第一章:认识 标识符
标识符顾名思义就是用来标示一些东西的符号,通常用来标示 变量名、函数名等等。
标识符的组成是由 字母、数字、下划线组成的一组 非数字打头的字符串。
例如:
Aa c4 mp3 admin_888 Cater_QQ_24882688_ _
这些都是合法变量,当然字母的大小写不同很可能在一些编译器中被认为是两个不同的标识符。
我们不需要看书上对标识符精确的定义,,反正你要知道表示符是用来标示一些东西的,所以名字要起的方便你记忆和明白他是干什么的,还有既然字母大小写会在一些编译环境中标示不同的标识符那我们就尽量控制使用。
第二章:认识常量
常量他标示一些确切的数值或字符串。
例如:
123 -7 0.5 ‘B’ “B” “QQ:24882688”
我们发现什么,通常 数值常量不需要加单引号或双引号。
字符串常量使用单引号或双引号成对标注起来的。
这里注意一下字符串用单引号标示和用双引号标示起来是不一样的
‘B’ 表示字母B
而“B” 则标示字母B加上个字符串结束标识(它的十六进制形式是0x00)
换句话说 ‘B’ 的字符串长度是 1,“B”的长度是2
第三章 :认识变量
变量是用标识符来标识的一组内存地址
所以问变量 A 等于 8 么 ?
他表示的是某某内存地址的内容是 8 么
也就是 A 这样的标识符最后他只表示某某地址的内容
例如 :
假如给 A的表示的内存地址是005201314 里面的内容,那么给 A 赋值123 的汇编语句是
MOV [005201314],0x0000007B //十六进制0x0000007B等于十进制的123
从这里我们也能看到高级语言C 的人性化,他形象的把上海XX区XX路XX号这么长的地址直接用Cater 家 这么一个干净简介的标识符来标示,不过这样的标示是给你和编译器看的,计算机CPU 可不认识 Cater 是什么,当然说 Cater家 它也不知道是什么飞机。所以在计算机CPU(汇编代码中)精确的定位了坐标 上海XX区XX路XX号 。
第四章变量类型
在C 语言中变量类型只有四种:整型、浮点型、指针、聚合性。
简单说变量类型就是表示一个 变量占内存空间长度 是多少字节。
| 类型 | 标示数值范围 |
| Char | 0 ~ 127 |
| Signed char | -127 ~ 127 |
| Unsigned char | 0 ~ 255 |
| Char家族定义变量值占内存的长度为1个字节 (Byte表示一个字节) |
| Short int | -32767 ~ 32767 |
| Unsigned short int | 0 ~ 65535 |
| Int | -32767 ~ 32767 |
| Unsigned int | 0 ~ 65535 |
| Int家族定义变量值占内存长度为2个字节 (Word表示一个字) |
| Long int | -2147483647 ~ 2147483647 |
| Unsigned long int | 0 ~ 4294967295 |
| Long int家族定义变量值占内存长度为4个字节 (DWord表示一个双字) |
| float | 占四字节 |
| double | 占八字节 |
| Long double | 占八字节 |
| 为什么我在定义浮点系列的时候只说数值占内存大小而不具体给出范围呢,简单解释下吧,其实些数据过于复杂不便于记忆,大家只要知道浮点可以标示正负小数就好,而四字节八字节也只是标示一个精度。通常float已经够我们正常使用了,实在不行就用double双精度。 |
以上的定义应该是在16位PC系统上所定义的
实际Int 型在32位PC系统上所占四个字节
从这个表我们得出什么?
找规律咯:
规律一:Unsigned 无符号的标示范围为 零 到 满值
例如:
Char类型在内存占用一个字节空间那么他的无符号数值范围为 0 ~ 0xFF (0 ~ 255)
Int 类型在内存占用两个字节空间那么他的无符号范围是 0 ~ 0xFFFF (0 ~ 65535)
规律二:Signed 有符号的标示范围为 负的(满值-1)除以2 到 (满值-1)除以2
例如:
Unsigned Int类型在 内存占用两个字节空间
那么 他的有符号数值范围为 –(0xFFFF-1)/2 ~ (0xFFFF-1)/2 也就是 -32767 ~ 32767
Unsigned Long Int 类型在 内存占用四个字节空间
那么 他的无符号范围是
–(0xFFFFFFFF-1)/2 ~ (0xFFFFFFFF-1)/2 也就是 -2147483647 ~ 2147483647
规律三:Int 为整型不能标示小数,float单精度,double双精度可以用来表示小数。
第五章指针
指针算是C语言中的精髓的地方了,有很多小菜被指针搞得头晕晕,小弟弟偶也是被指针搞得晕晕滴,那我们下面就详细拆解下指针咯。
指针是一种特殊的变量,它大致先查询一个变量A的地址,把A地址中的内容作为取数据的地址。
好,到这里不懂,且不说你白痴。
我们先继续说
先复习下 第三步 认识 变量中 关于变量的描述
变量实际是简化内存地址的标示
假如变量A他表示内存地址005201314 里的内容,那么给 A 赋值123 的汇编语句是
MOV [005201314],0x0000007B //十六进制0x0000007B等于十进制的123
好首先 理解下他们的含义
A 表示 一个变量,表示的是 内存地址 005201314 中的内容
举个例子005201314 表示一个小区,A就表示这个小区里有多少人
&A 表示 A 变量在内存中的存放地址,数值当然就是门牌号码 005201314
举个例子 某某业主住哪里?
*A 表示 将 A 地址中的内容 作为 下一个地址B,去访问B地址中的内容
把上面中文翻译成表达式就是 B=[&A] 然后 [B]
即 b=[00521314]=123 然后 再访问 内存地址为 123 的内容
这样的访问是 间接访问。
相当于 从 派出所 查到 你住的小区,从你住的小区查到你家有几口人。
他们的关系 就相当于,有一个小区里有123人(A),
这123个人住在上海长宁区某某路某某小区里(&A),
我要找这个小区最后一个业主(设小区门牌编号从1开始顺序排列)
过程就是,先找到这个小区&A,看里面一共有多少人[&A],最后找到最末尾的那个业主 [[&A]],也就是说 *A 它等于 [[&A]]。
好了去理解下吧。
半个小时内任然无法理解的,以后可以不用看我写的东西了。 ^_^
第六章指针的类型定义
#include "stdio.h"
void main(void)
{
char *a;
long *b;
long c=0x12345678;
a=&c;
b=&c;
printf("%x %x",*a,*b);
*b=0x05201314;
printf("\n%x %x",*b,c);
}
假设 &c=00521677
c=0x12345678 在内存中的表示如下
| 内存地址(十六进制) | 0x00521677 | 0x00521678 | 0x00521679 | 0x0052167A |
| 数值 (十六进制) | 0x78 | 0x 56 | 0x34 | 0x12 |
即 a=&c=0x00521677
b=&c=0x00521677
*a=[0x00521677]=?
*b=[0x00521677]=?
他们的指针是一样的指向 内存地址 0x00521677 这里的内容
但是输出缺不相同
这里就是指针类型定义定义不同
Char *a
意思就是 *a= [0x00521677] 这里的数据以char 类型定义
long *b
意思就是 *b= [0x00521677] 这里的数据以 long 类型定义
之前我们也说道
变量类型就是表示一个 变量占内存空间长度
既然 *a是以 char 类型定义 所以 *a=[0x00521677] 这里的数据是以单字节长度定义
单字节也就是只访问 以 0x00521677 做开始的一个字节 也就是 [0x00521677] 单元
即 *a=0x78
而 *b是以 long 类型定义 所以 *a=[0x00521677] 这里的数据是以四字节长度定义
四字节也就是访问 以 0x00521677 做开始的四个字节 也就是[0x00521677] [0x00521678] [0x00521679] [0x0052167A] 四个单元\,当然数据在内存中的存储反序的即高地址在前低地址排在后面
所以 *b=0x12345678
然后到
*b=0x05201314;这一句
因为
b=&c= 0x00521677
那么
*b=*(&c)=c
所以
给*b赋值也等于给 c赋值
c 是 [0x00521677] 的简化表示
*b 也是 [0x00521677] 的简化表示
既然 [0x00521677] 里的内容变了
那么
c也等于*b等于5201314咯。
第七章:左值右值以及表达式
表达式:在我的理解就是一组赋值的语句。
例如:
A=123 QQ=”24882688” s=w * h u=U i+=1 k=A+9 j++
还记得之前对变量的解释么?
A变量代表的是个内存地址假如A的表示的内存地址是005201314 里面的内容,那么给 A 赋值123 的汇编语句是
MOV [005201314],0x0000007B //十六进制0x0000007B等于十进制的123
表达式A=123 实际就是给内存地址是005201314 里面的内容写入数据 123
这样的赋值表达式就是把一些数据写到某个内存地址存储起来。
何为左值
A=123
这里 A 作左值 123 作右值
实际是将”=”右边的数据存储到左边地址中
左值其实就是一个存储地址
如果A 放在”=” 右边那么 A就是一个右值
何为右值
A=123 B=C
123 和 C 就是右值
右值实际是一个具体数据或数值
左值和右值的关系
假设
&K=005201310
&A=005201314
也假设005201314 地址内容中数据是 123(即 A=123)
005201310 地址内容中数据是 456(即 K=456)
那么
表达式 K=A
实际是在K 的内存地址写入A的数据内容
[005201314] ==> [005201310]
左值和右值的最大区别就是左值是存储地址右值是数据内容
左值和右值能不能调换位置
只有当两边都是单一变量的时候才可以相互交换位置,
因为变量具有固定内存地址
举例
A=B+C 和 B+C=A
A 有固定地址
B、C也有固定位置
因为他们都是变量
但是
A=B+C 或 B+C=A
实际上是先进行
B 和C 的加法运算,运算结果为一个临时变量,假如我们用Temp来标示,也就是说temp为临时变量没有固定地址,不过他可以标示一个数值
既然 temp是数值,那么 他只能作右值。
写这篇文章是CaterQiu学习汇编后重新对C的温故,里面多处从汇编角度看待C语言中的变量相关问题,这七章主要就变量问题展开学习。
本来是打算再写七篇中卷介绍程虚函数等等的,现在看看估计也没什么可能了,呵呵。老黄牛CaterQiu同学改行了。
仅此献上这篇未完成的札记给学习C语言的初学者,希望对他们能有帮助。