当前位置 博文首页 > 海砸的博客:【c语言】带你真正走进指针的世界——指针的特性

    海砸的博客:【c语言】带你真正走进指针的世界——指针的特性

    作者:[db:作者] 时间:2021-06-14 21:47

    ? ? ? ? ?当你看到这篇文章时,请忘掉你之前对指针的所有认知,什么地址什么的统统忘掉。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 我来给你们重新构造一个全新的指针世界。

    ?首先,我们知道,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语言的变量存在,地址是它的最主要的功能,但不是全部功能,在下一篇文章中将会逐渐带大家一步一步深入指针的世界。

    下一篇:没有了