小白爬坑记:C语言学习点滴——我对变量、指针的理解
学过了指针后,对变量又有了一些新的认识,特记录下来这些点滴知识,逐步提高自己!
一、什么是变量
搜索得到:变量来源于数学,是计算机语言中能储存计算结果或能表示值的抽象概念!
嗯,虽然抽象,那也需要有个名来指代一下。就有了变量名。
我理解的变量名,就是给变量套一层衣服,你随意变,我知道衣服里面是你这个值就行。
另外变量还需要控制一下变化的范围大小,就有了变量的类型。
(例如:short、int、long、char、float、double、boolean等)
自己理解:变量类型作用就是——限定变量的范围存储长度
例如: int num;
两个信息
1、变量的名称: num ——》(包装变量值的外衣num)
2、变量的类型:int ——》(规定了变量值的大小范围,4个字节)
在内存中num就是一个地址位置,要用“&”加变量名就获取到存储变量的地址。
变量名与地址是同一个东西,它就是个壳、就是个外衣,它里面存储了一个值。
让人看的是变量名num(好记),让机器看的就是个内存地址。以这个地址为起点之后的4个字节来存放这个值。
二、变量类型的界定:(非常重要)
什么意思呢?我自己说不太明白,毕竟小白过的坑还少,C语言中遇到的,必须说明白,还是举例子吧!
例子一:
int a[10];
假如给a赋值:小白时候肯定犯过同样错误,用这个错误来说明
a = 5;
编译提示:
error C2440: “=”: 无法从“int”转换为“char [10]”
看到这句提示:编译器明显告诉你
a 的类型是 “char [10]”
例子二:
int* b[5][10];
给 b 再赋值一个int常数
b = 10;
编译提示如下:
error C2440: “=”: 无法从“int”转换为“char *[10][5]”
b 的类型是 “char *[10][5]”
从上面两个特殊例子可以一窥C语言的变量类型的界定。
两个例子总结如下:
将定义变量时的变量名去掉后,剩余的“所有符号标志”统称为变量的类型。(紧扣字眼,非常重要,关系到各种变量之间的转换)
许多童鞋被变量间的赋值、转换弄的晕头转向,甚至都不知道从哪入手变量的赋值(紧抠住字眼,让你在C语言的各种变量间畅通无阻)
来个小练习:
练习:
说出如下几个变量的类型:
1、int c; ————> c 是 int 型变量
2、int* d; ————> d 是 int* 型变量
3、char** e[5] ————> e 是 char** [5] 型变量
4、short* sh[1][2]; ————> sh 是 short* [1][2] 型变量
5、long******* f;————> f 是 long******* 型变量
6、char******** x;————> x 是 char******** 型变量
上面都记忆好了吗?都熟练了吧?
咱再来练几个复杂的:
牢记:扣字眼
char** num; ————> num 是 char** 型
char** num; ————> *num 是 char* 型
char** num; ————> **num 是 char 型
char** str[5]; ————> *str 是 char** 型
仔细看上面 *str 的类型 有点晕么?怎么多出来一个 “ * ”
留个扣子,下面指针时候咱再来解,为什么会多一个“ * ”
变量的赋值原则:
变量赋值时候,“ = ”左边和右边必须是相同类型的变量才能够进行赋值,如果变量类型不同,还需要赋值,就必须进行强制转换。
强制转换数据类型,只要变量前加要强制转换的类型名用括号括起来即可。
例子:
int a;
char b;
short* c;
a = (int)b;
c = (short*) a;
别管上面啥意思,只要将“ = ” 赋值号两边类型搞的一样就随便了!
三、什么是指针
简单说:指针就是一个内存地址
指针的作用一:就是为我们做引导,让我们找到一个地址、或是一个值。
根据上面变量变量类型的界定我们要先举个小例子:
我们来定义一个指针:
(我自己理解,其实指针就像个“路牌”)
例一:
int *p;
int a;
我们说 p 的类型是 “int * ”类型
那么,*p 的类型是“ int ” 类型
我们可以看出: *p 本质就相当于变量值 。
*p 在运算或赋值的时候就相当于 变量名 a 的作用;
*p 等同于 a 的作用 他们俩都是存放变量的容器(是变量值的外衣)
“变量名”(各种帮助记忆、有意义的符号组合)就是“变量地址”的代称。
★牢记,后面有用
变量的地址值获取方法:
例二:
int str;
int *p
p = &str ;
上面两边类型一样么?
当然,因为左边带星是地址,右边也用&取了变量地址,所以相等
符号“&”作用是取变量地址符号。
★牢记
我们来使用指针:
既然是个路牌,我们就与变量结合起来。让它指向一个变量值
例三:
int *p;
int str;
str = 666;
p = &str;
printf("存放666的容器地址是:%x",p)
我们打印指针存储的数据需要用 %x 十六进制格式来查看内存存储的地址值
而我们的目的不是要获得地址,我们是要获得具体的哪个变量的值“666”
那我们就用指针来取值,如下:
printf("%d",*p);
一个类型中,只要带有“*” 星号,肯定没跑,就是指针,只要是指针,它就是地址,那它的长度就占 4 字节(32位系统地址表达方式占4字节)。
指针与其他类型之间的转换与赋值:
这里就必须灵活的运用变量的类型了:
例四:
char* a1;
char f;
f = *a1;
char* a1 是 a1是 char* 类型
那么 *a1 就是 char 类型
所以上面赋值等式是成立的。
指针就是用指针变量保存一个指向某地的地址:
int *p_addr;
int str;
p_addr = &str;
“&” 是取地址的意思,取出存放str变量值的地址
int **P;
p = &p_addr;
因为要保存 int* 类型的 p_addr 变量地址,就必须定一个 int** 的变量
指针与数组间的关系与转换:
数组:就是多个相同变量的集合。
例五:
int str[10];
int *p;
又因为 str[0] 是 str[10] 这个数组的第一个值。
从上面的(例一)中可知,所有的变量名都是一个地址的代称,那么str[0]这个
变量名就是一个地址。
那么,str[0] 就可以看成 变量的一种寻址 (str + 0) 的寻址,(在内存的
栈中可以观察数组存放的结构)
(简单算数)任何地址加零 仍是这个地址。
因此 str[0] <==等同于==> str;
同理,所有的变量名都是一个地址的代称,那么"str"
这个变量名也是一个地址,那么这个地址通过上面的推导,也是str[10]数组
的 “入口”。 那么 str 不就与指针同一个作用了么?
p <==等同于==> str
*p <==等同于==> str[]
终于揭开了变量界定时,多一个“ * ”的原因,方括号就等同于一个“ * ”
*(p + 0) <==等同于==> (str + 0)[]
那么我直接用P去寻址就OK了,无非就是按照类型加N个字节寻址罢了:
因为 str[10] 是 int 类型(数组每个“值”占4个字节)
那我就定一个同样类型的指针不就结了!
因为 *p 也是 int 类型(1个*p 的值也占4个字节),寻址长度一样。因此,
我就可以得出结果:
str[0] <==等同于==> p[0]
str[1] <==等同于==> p[1]
str[2] <==等同于==> p[2]
str[3] <==等同于==> p[3]
......
用指针寻址替代数组寻址的理解!推导完毕!
指针的作用二:做中转来改变某个地址值后面的寻址长度
例如:一个 int 类型的变量name,它的内存表达长度为 4 个字节,那我要找与它类似的值的长度,就得略过这个 name 变量,让它的地址加1,到下一个位置:
例子:
int *p;
int number;
p = &number;
变量 P 存储着number的地址值,我们让它寻址就是:
用p 存储的地址值 + 1
p = p + 1;
那么在内存中就会表现为跳过 4 个字节,指向之后的地址,这是按照变量
p 的 int(4字节)类型进行的寻址。
很多时候,我们下一个数据并不一定是 int 类型,有可能是 char 类型
char仅仅是一个字节,那我们要是用 int 类型寻址方式,就无法获得正确
的 char 值。
我们就可以通过“强转指针类型”的方式改变它的寻址长度!如下:
char *number1;
char one_byte;
number1 = (char*)p;
one_byte = number[0];
如果对您有哪怕一捏捏帮助的,请您抬抬贵手,点赞、收藏~感激不尽!!
以上就是我对 变量 、指针的认识理解!!!不足或错漏的地方,还请各位路过的大神批评、斧正!!!
如果对您有哪怕一捏捏帮助的,请您抬抬贵手,点赞、收藏~感激不尽!!