当你看到这篇文章时,请忘掉你之前对指针的所有认知,什么地址什么的统统忘掉。
我来给你们重新构造一个全新的指针世界。
首先,我们知道,c语言中有很多种变量类型
int a ;
short b;
char c;
.
.
.
而c语言中还有一种,可以在变量后加一个符号 “ * ” 成为一种全新的变量
int* a;
short* b;
char* c;
这个变量就是c语言中的指针变量,指针的定义就是这么简单,不像网上或者某些书本上故弄玄虚地说着指针的定义
好像故意把我们往错误的道路使劲推似的......,其实指针并不难理解,下面由我来给大家解释下指针的特性~
我们经常以这样的方式给变量赋值
而事实上,我们这样的赋值写法只是一个简略写法,真正的赋值写法应该是这样子的
然而,虽然我们用的是简略写法,但是编译器是允许我们这样做的,然而,在给指针赋值时,就必须用完整的赋值方法。
如上图为使用简略写法赋值,编译器报错
图上为使用详细写法后的赋值,编译通过
既然在变量之后加上 “ * ” 可以变成一个新的变量,那么就可以2个或者无数个 “ * ” 来声明更多的新变量了~
编译安全通过~~
讨论完如何给指针赋值之后我们讨论下指针的宽度
#include <stdio.h>
#include <string.h>
int main()
{
char* a;
short* b;
int* c;
a = (char*)1;
b = (short*)2;
c = (int*)3;
return 0;
}
我们以上面代码为例
众所周知,当图上的变量 a、b、c 分别为char、short、int 时,所占据的字节数分别是1byte、2byte、4byte,而当我们在这些变量之后加上 “ * ” 时,所占据的字节数是否有所变化?
我们把c语言转换成汇编语言可以看出,三个指针变量虽然声明不同,但是都是同样占据4字节!
那么我们的符号 “ * ” 如果不止一个的话搜占据的字节也是一样的吗?
我们以此代码为例
由c语言转汇编语言可得知,带 “ * ” 类型的变量宽度永远都是4字节,无论什么类型,无论有多少个 “ * ”
当我们看到这样的一个程序时
#include <stdio.h>
#include <string.h>
int main()
{
char a;
short b;
int c;
a = 100;
b = 100;
c = 100;
a++;
b++;
c++;
printf("%d %d %d",a,b,c);
return 0;
}
很容易就可以得出这样的结果
而当代码改为 指针 自增一时
#include <stdio.h>
#include <string.h>
int main()
{
char* a;
short* b;
int* c;
a = (char*)100;
b = (short*)100;
c = (int*)100;
a++;
b++;
c++;
printf("%d %d %d\n",a,b,c);
return 0;
}
得出的结果却是这样的
原因是因为:指针和常变量的计数方法不同,指针的加减法原则如下
所以,图上代码中的 a 为char* 类型的变量,其值为 100 ,当自增一时,去掉符号 “*” 后剩下 char 类型,而 char 类型是 1字节 的,所以是 100+1 = 101;
再者,图上代码中的 c 为 int* 类型的变量,其值为 100 ,当自增一时,去掉符号 “*” 后剩下 int 类型,而 int 类型是 4字节 的,所以是 100+4 = 104;
而当代码是下面这个样子的话
#include <stdio.h>
#include <string.h>
int main()
{
char** a;
short** b;
int** c;
a = (char**)100;
b = (short**)100;
c = (int**)100;
a++;
b++;
c++;
printf("%d %d %d\n",a,b,c);
return 0;
}
得到的结果是这样的
这是因为代码中的 a 为char** 类型的变量,其值为 100 ,当自增一时,去掉符号 “*” 后剩下 char* 类型,而 char 类型是 4字节 的,所以是 100+4 = 104;
另外两个变量推理类似,所以,当是指针加上其他整数时
#include <stdio.h>
#include <string.h>
int main()
{
char* a;
short* b;
int* c;
a = (char*)100;
b = (short*)100;
c = (int*)100;
a = a+5;
b = b+5;
c = c+5;
printf("%d %d %d\n",a,b,c);
return 0;
}
其结果为:
由上面的推理可得知:代码中的 c 为int* 类型的变量,其值为 100 ,当+5时,去掉符号 “*” 后剩下 int 类型,而 int 类型是 4字节 的,所以是 100+(5X4) = 120;
其他推理类似......
———————————————取值 “ * ” 和取址“ & ”————————————————
当我的代码是在这个样子的时候
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",p1);
return 0;
}
得到的结果是这样的
显而易见,p1里面保存的是 X 的地址。然而,我为什么不可以直接这样写呢?
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = x;
printf("%d\n",p1);
return 0;
}
编译器尴尬又不失礼貌地回答说
根据编译器所给出的原因,我们可以理解到,是因为赋值符号 ” = “ 两边的类型不相等(一个是 int 型,一个是 int * 类型)造成的,那么为什么加了 ” & “ 就可以了呢? 其实在编译器里面 , ” & “ 有个专业名字 ,叫做取址运算符,它的作用是在类型后面自动加上一颗 ” * “ ,使得变量看起来更高大上一点~~ ,所以如果是直接的 int* p1 = x,由于 x 是 int 类型的 ,而 p1 是 int* 类型的,所以不能把 x 的值赋值给 p1 ,这个时候就需要用到 ” & “ ,在 x 的类型 int 后面加上一颗 ” * “,使得两者类型相同,有点类似于强制转换。
和 “ & ” 相反的是 “ * ”,它在声明变量时代表的是指针,但是在其他地方使用时是和 “ & ” 反过来的,它的作用是去掉一颗 “ * ” ,比如以下代码
#include <stdio.h>
int main()
{
int x = 100;
int* p1 = &x;
printf("%d\n",*p1);
return 0;
}
得到的结果是
“ * ” 在代码的作用是,去掉 &x 的一颗星,也就相当于去掉 “ & ” 给加上来的那颗星,就会得到 int 类型的 x ,即int 类型的 100。