【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。

       懂得以上对于指针的基本知识,即对指针的基本特已有所掌握,知道现在为止,文章还没半个字提到地址这个概念,这是因为指针其实是做为一个c语言的变量存在,地址是它的最主要的功能,但不是全部功能,在下一篇文章中将会逐渐带大家一步一步深入指针的世界。

猜你喜欢

转载自blog.csdn.net/qq_41884002/article/details/84258830