当前位置 博文首页 > 海砸的博客:【c语言】带你真正走进指针的世界——指针的特性
?首先,我们知道,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。