指针变量的运算
指针变量不能相加 不能相乘 也不能相除
如果两个指针变量指向的是同一块连续空间中的不同存储单元
则这两个指针变量才可以相减(比如你有个门牌号一个西安某个小区门牌号,一个是上海某个小区门牌号,相减没有意义,要同一个小区)
一个指针变量到底占几个字节
# include
int main(void)
{
char ch = 'A';
int i = 99;
double x = 66.6;
char * p = &ch;
int * q = &i;
double * r = &x;
printf("%d %d %d\n", sizeof(p), sizeof(q), sizeof(r));
return 0;
}
先记住
// 指针就是地址,地址就是指针
//p 也是个指针变量,有空间,需要4个字节保存,地址就是内存单元的编号,有32根地址总线来组合
( 一个指针变量无论它指向的变量占几个字节,它本身都只占4个字节)
计算机就分配了p q r 4个字节的地址给你,你用多少是你的事情,比如门牌号: 0000 0000 0000 0000 0000 0000 0000 0001
预备知识:
sizeof(数据类型)
功能:返回值就是数据类型所占的字节数
例子: sizeof(int ) = 4 sizeof(char ) = 1
sizeof(double) = 8
sizeof(变量名)
功能:返回值是该变量所占的字节数
假设 p 指向char 类型变量(1个字节)
假设 q 指针int 类型变量(4个字节)
假设 r 指向double 类型变量(8个字节)
p q r 本身所占的字节数是否是一样?
答案: p q r 本身所占的字节数是一样的(4个字节)
char int double ,它们在32个状态表示形式不同,char类型就只有一个字节,只能指向第一个字节地址,p 本身4个字节 需要 4个char类型地址分配空间
int类型4个,但定义的q只指向4个字节的第一个字节地址
double8个字节,而r只指向字节地址,r 本身占 4个 ,也就是相当于一个double类型可以分配2个 r 指针变量地址
int * p = (int *)malloc(4); // malloc 动态分配
// p 指向4个字节,但p本质上只保存了第一个字节地址,4个字节只用首地址表示,int *类型已经让我们知道是4个字节为一个变量单元了
// p本身身为指针变量只能指向第一个字节地址,但是 p 前面定义了数据类型 int ,达到的效果是 p 可以指向4个
而不同变量类型的首字节都是由32根地址总线的不同状态组成的(4*8 = 32 位)
(
// 房子,如果房子就只有两栋,编号就很小
// 假如房子很多很多,10000个房子,第一个房子的大小和它本身的编号大小不是一个概念
设有一万个房子 , 某一个房子本身可以很小, 但因为房子本身比较多,编号就很大
)
也就是p q r 的(首)字节大小(地址编号)是由计算机本身所分配的地址大小确定的(32位)
与p q r 本身数据类型的实际大小无关(数据类型只能决定 p q r 让系统分别分配多少个)
计算机就分配了p q r 4个字节的地址给你,你用多少是你的事情,比如门牌号: 0000 0000 0000 0000 0000 0000 0000 0001
一字节:8bit: 0000 0000
总结:
一个指针变量,无论它指向的变量占几个字节
该指针变量本身只占四个字节
指针变量本身保存的是一个地址,而这个地址的位数最多也就32位(32位的机子)
所以4个字节乘以8位,就是32位了,正好能够满足存放一个最大地址的需要。
一个变量的地址使了该变量首字节的地址来表示的。
指针变量是通过数据类型和首字节的地址拿出的所有数据 *p
# include
int main(void)
char ch = 'A';
int i = 99;
double x = 66.6;
char * p = &ch;
int *q = &i;
double * r = &x;
printf("%d %d %d\n", sizeof(p), sizeof(q), sizeof(r));
// x 占8个字节,一个字节算一个单元,一个字节一个编号(8个0或1一个编号,一个字节占8位)
// x 有八个字节, 第一个编号当作了x 的编号,char指向第一个字节(只有一个字节), int 指向第一个字节,把第一个编号当作的标志
// 只保存各自类型的第一个字节的编号(地址)
// p q r 都指向的是 各自的第一个地址,但它们各自总体长度是几,靠的是它们各自定义的char int double 决定的
// 一个变量地址只用第一个字节地址表示
// 虽然它们三个指向第一个字节地址,但他们本身指针变量类型就可以确定出它到底指向的变量占几个字节
// p q r 都只占4个字节,它们都存放第一个字节地址,而它们输出长度又是4,就意味着说我们的第一个字节地址要用4个字节表示
// p q r 中只存放了一个字节的地址,但是 p q r 却占 4 个 字节? -- 说明地址占4个字节,或者这个编号,虽然 p 是第一个字节地址,但是第一个字节地址它是个编号,编号本身需要4个字节
// 编号本身需要4个字节去保存
// 房子,如果房子就只有两栋,编号就很小
// 假如房子很长很长,10000个房子,第一个房子的大小和它本身的编号大小不是一个概念
// 假设有一万个房子 , 某一个房子本身可以很小, 但因为房子本身比较多,编号就很大
// 虽然 p q r 只占一个字节,但是字节太多了,编号就比较大,大的编号刚好用 4 个 字节去表示
// 那为啥是4个字节呢?
//CPU 里面控制内存有 32 根线 , 一根线有两个状态(0、1),一共 2^ 32个状态,不同的状态可以确定一个单元(一个字节算一个单元)
// 因为地址总线是32 位,所以编号有 4G 个编号,第一个编号和第二个编号都需要 32 根线,只不过是用了 32 根线不同的状态去表示
// 比如第一根线,编号可能是 0 的地方编号是 0000 0000 0000 0000 0000 0000 0000 0000
// 第二个地址(第二根线),编号可能是编号是 1111 1111 1111 1111 1111 1111 1111 1111
// 32 根线可以确定 4 G 个不同个状态
// 无论是第一个状态还是最后一个状态,或者说无论是第一个编号还是最后一个编号,它都要4 个 字节去保存,最终 p q r 里面都占 4 个字节(4个字节就是 32位, 4*8 = 32)
// 32 根线就是32个比特 也就是4个字节
// 我们内存中的第一个编号肯定从零开始的,最后一个编号肯定是很大了
//无论是第一个编号还是最后一个编号,它们都是用32根线来表示的,它们都需要在内存里面用4个字节去保存
//第一个编号只不过是32根线加上零: 0000 0000 0000 0000 0000 0000 0000 0000
// 也就是这个地址由32个二进制组成,一个字节存放8个二进制位所以4个字节
// 一根线代表1bit,32根线需要32bit,1字节=8bit
return 0;
mysql数据类型 int、tinyint、float与decimal的区别
1.int、tinyint、float.
它们都是(精确)整型数据类型,但是占用字节数和表达的范围不同。首先没有这个表就说不过去了:
只需要知道对应类型占多少字节就能推算出范围了,比如int占 4 bytes,即4*8=32bits,大约10位数字,也能理解为什么int默认显示位数是11。
遇到比较多的是tinyint和bigint,tinyint一般用于存放status,type这种数值小的数据,不够用时可能会用smallint。bigint一般用于自增主键。
为了避免数据库被过度设计,布尔、枚举类型也采用tinyint。
需要注意的是:无论是定义为int(4)还是int(11)。所占用的存储空间是一定的。int(M)中的M只是代表显示的宽度。
2.float与decimal
MySQL使用DECIMAL类型去存储对精度要求比较高的数值,比如金额,也叫定点数,decimal在mysql内存是以字符串二进制存储的。声明语法是DECIMAL(M,D),占用字节 M+2 bytes。M是数字最大位数(精度precision),范围1-65;D是小数点右侧数字个数(标度scale),范围0-30,但不得超过M。
也就是说decimal可以动态的规定占用字节的多少。
decimal计算占用字节数的方法:
占用字节数计算方法 —— 小数和整数分别计算,每9位数占4字节,剩余部分如下表换算:
比如DECIMAL(18,9),整数部分和小数部分各9位,所以各占4字节,共8bytes
再比如DECIMAL(20,6),整数14位,需要4字节存9位,还需3字节存5位;小数6位,需3字节。共10bytes
例如:定义一个decimal(7,3),所能表示的最大数值为-9999.999~9999.999.占用4字节。
123.12 -> 123.120,因为小数点后未满3位,补0
123.1245 -> 123.125,小数点只留3位,多余的自动四舍五入截断
12345.12 -> 保存失败,因为小数点未满3位,补0变成12345.120,超过了7位。严格模式下报错,非严格模式存成9999.999。
单精度浮点数float占4字节,float标准语法允许通过FLOAT(M)的形式指定精度,但是这个精度值M只是决定存储大小: 0-23与默认不指定效果相同,24-53就变成双精度的DOUBLE了。
double 和 float 的区别是double精度高,有效数字16位(float精度7位)。但double消耗内存是float的两倍,占8字节,double的运算速度比float慢得多。