Code前端首页关于Code前端联系我们

C语言指针是纸老虎,看5个方面

terry 2年前 (2023-09-25) 阅读数 49 #后端开发

我们来看看5个维度。不过在我们说话之前,我先写了一个程序,其中包含了指针的“两个自体和三个其他”维度,然后一一解释了每个维度的含义。看看是否会出现这种情况。

在大多数使用指针的场景中,这5个维度应该足以帮助你理解。但是,在一些使用指针的特殊场景下,5维方法可能就帮不了你了。

长文提前警告,如果你不耐烦,可以将这篇文章加入书签,有时间再读一遍。

1。程序代码

1.1。代码

Instance

#include

int main(void)

{

int *pInt = NULL;int *pInt = NULL;: 0X %x\n", &pInt);

//printf("指针变量值 pInt: 0X%x\n", pInt);

int para = 1;

printf("地址para 变量: 0X%x\n", &para);

printf("Para 变量值: 0X%x\n ", para);

  pInt = ¶

  printf("Para 变量值指针 pInt : 0X%x\n", pInt);

  printf("指针变量值 pInt 另一个值: 0X%x \n", *pInt);

int arr_int[2] = {1, 2 };

pInt = arr_int;

printf("arr_int 第一个元素 arr_int[0 ] 地址:0X%x\n", pInt);

printf("arr_int 第二个元素 arr_int ] 的地址是: 0X% x\n", pInt + 1);

double *pDouble = NULL;

double arr_double[2] = {1.1, 2.2}; = arr_double printf("arr_double第一个元素 arr_d ouble[0] 的地址为:0X %x\n", pDouble);

printf("arr_double arr_double[1] 第二个元素的地址为: 0X% x\n", pDouble + 1 );

返回0;

}

运行结果如下:我文章中的

C语言指针是个纸老虎 5个方面看穿它

当我理解一些东西时,我喜欢用一个非常简单的程序来解释。所以那些认为你应该用圣经这样的程序来解释你的观点的人,或者那些鄙视低级程序的人,不要忘记我^_^。

2.2。 Para int 类型变量

在程序中:

int para = 1;
printf("变量para自己的地址是:  0X%x\n", &para);
printf("变量para自己的值是:  0X%x\n", para);

定义了para变量,它有自己的数据值和自己的存储地址。这一切都很容易理解。从运行结果来看,para变量的数据值为十六进制的“0X1”,地址为十六进制的“0X22feb4”。也就是说,在内存中,从地址“0X22feb4”开始的存储空间有4个字节存储数据值“0X1”。在我的机器上,int变量占用4个字节,在你的机器上可能有所不同。

大家都能轻松理解int类型变量para。接下来我画一个示意图来展示变量在内存中是如何存储的,如下:

C语言指针是个纸老虎 5个方面看穿它

先从“两个自己,三个别人”的概念开始。

2. 两个和另外三个

“两个和另外三个”,扩展起来就是:自己的地址、自己的值、值、其他地址、其他类型。

2.1。地址吉

2.1.1 “地址吉”的概念

“地址吉”是“自己的地址”的缩写。作为变量,指针 pInt 与变量 int para 一样,也必须存储在内存中的存储位置中。这个存储空间也会有一个起始地址,即指针变量pInt也会有自己的地址。上面提到了para变量的地址是“0X22feb4”,那么指针变量pInt的地址是多少呢?

2.1.2 获取“地址”

我们都知道“&”是获取地址的运算符。程序中:

printf("指针变量pInt自己的地址是:  0X%x\n", &pInt);

使用“&”来获取指针变量 pInt 的地址。从运行结果来看,指针变量pInt的地址为“0X22feb8”。在我的机器上,指针变量pInt也占用4个字节。因此,指针变量pInt被存储在起始地址“0X22feb8”开始的4字节空间中。 ?添加pInt指针变量的“地址”,表示pInt指针变量在内存中的存储方式。

C语言指针是个纸老虎 5个方面看穿它

“吉吉”,就是这个意思。你看,没有什么是那么困难的!

2.2 自身价值

2.2.1 “自身价值”的概念

“自身价值”是“自身数据价值”的简称。作为变量,pInt 指针与 para 变量一样,也有自己的数据值。

2.2.2 获取“自己的值”

上面提到了para变量的数据值为“1”,那么指针变量pInt的数据值是多少。程序中:

pInt = ¶
printf("指针变量pInt自己的值是:  0X%x\n", pInt);

我使用“&”运算符将para变量的地址值赋给指针变量pInt,并使用printf返回指针变量pInt的数据值。从运行结果来看,指针变量pInt的数据值为“0X22feb4”。我们再看一下。 para变量的地址也是“0X22feb4”。所以,这条语句

pInt = ¶

的本质就是将变量para的地址赋值给指针变量pInt的值,从而将指针变量pInt绑定到变量para上。一起。

如《我的地址》中提到的,pInt指针的数据值存储在以地址“0X22feb8”开始的4字节内存中,也就是说内存以地址“0X22feb8”开始,下面的4 bytes 用于存储数据值“0X22feb4”。

2.2.3 如何写“自己的值”的代码

代码中写了如何写指针变量pInt的“自己的值”的代码。常见的代码编写方式是

pInt;

,部分代码的编写方式是:

pInt + N;
pInt - N;

编写方式是在“自值”pInt 中加上数字 N 或减去数字 N。这一点在我们谈论“其他类型”属性时会提到。还有一种写法:

pIntA - pIntB;

这种写法是指用“自己的值”来减去两个指针变量。

2.2.4 示意图

现在继续添加上面的原理图,并添加指针变量pInt 的值。

C语言指针是个纸老虎 5个方面看穿它

所以,一般来说,指针变量pInt的“自身值”就是数据值本身;对于其他int类型变量,它是地址。

2.3 其他地址

2.3.1 “其他地址”的概念

“其他地址”的概念是指“他人的地址”。事实上,上面提到自我价值时,并没有明确提到“其他地址”的概念。

2.3.2 获取“其他地址”

整数变量para存储在从内存地址“0X22feb4”开始的4个字节中。在程序中,我通过

pInt = ¶

将para变量的地址赋值给pInt指针变量,从而将pInt指针变量和para变量绑定在一起。更重要的是,“别人的地址”被赋值给了指针变量pInt的“自己的值”。这里,“他人地址”中的“他”指的是para变量,“他人地址的地址”。 “地址”指的是para变量的地址。记住,你看,“其他地址”和“自己的值”与数据值相同,所以,你已经知道发生了什么了吗?

很多教科书都说“指针是一个地址变量,它存储着另一个变量的地址”。显然,这意味着“其他地址”维度中的数据值与“自身值”维度中的数据值相同。课本上并没有说清楚。

2.3.3 示意图

我们再添加一个示意图,这次添加“另一个地址”的概念。

C语言指针是个纸老虎 5个方面看穿它

2.4 其他值

2.4.1 “其他值”的概念

“其他值”是指“其他人的数据值”。

2.4.2 获取“其他值”

在程序中,我通过

pInt = ¶

将para变量的地址赋值给pInt指针变量的“自己的值”,从而将pInt指针变量绑定到para 变量。设置在一起。此时,“他人的数据值”的“he”指的是para变量,“他人的数据值”的“数据值”指的是para变量的数据值“1”。在程序中,我使用

printf("指针变量pInt的他值是:  0X%x\n", *pInt);

,即在指针变量pInt前面添加“*”,返回指针变量的“其他值”。从运行结果来看,是“0X1”。记住,你看,指针变量pInt的“其他值”与para变量的数据值相同。你可知道?想不通吗?一直在看!

2.4.3 “其他值”代码写法

代码写法在代码中经常见到,比如*pInt怎么写,什么意思?事实上,它计算的是指针变量pInt“他值得”!

如何写:*(pInt + 1), *pInt + 1, pInt[1]?

*(pInt + 1):如果pInt + 1被认为是另一个指针,比如

int *pTemp = pInt + 1;

,那么*(pInt + 1)的计算意味着指针变量pTemp的“另一个值”;

*pInt + 1:这是使用pInt的“其他值”加1;

pInt[1]:怎么样?事实上,它是*(pInt + 1)。

2.4.4 示意图

继续在上图中添加,这次添加“其他值”的概念:

C语言指针是个纸老虎 5个方面看穿它

2.5 其他类型

2.5.1 “其他类型”的概念

C语言指针是个纸老虎 5个方面看穿它

”,是“别人”的缩写。在程序中,我们看到在声明指针变量pInt时,是这样写的:

int *pInt = NULL;

指针变量pInt前面的“int”并不代表指针变量pInt的“值”是数据。该值是int类型;相反,它意味着指针变量 pInt 的“另一个值”是“int”类型的数据值。这里指针变量pInt的“其他值”是变量para的数据值“0X1”。因此,指针变量pInt前面的“int”表示数据值“0X1”是“int”类型。

换句话来说,声明指针时的类型是用来修改“另一个值”的,而不是“你自己的值”。

再看一下,声明para变量时:

int para = 1;

para变量前面的“int”表示para变量的类型是整数,此时的“int”就是“自变量” type" for para",意思是“类型本身”。声明时唯一的指针类型是“other type”,即“其他类型”。

因为“其他类型”是用来修饰“其他值”的。” ,在声明指针时添加这个“其他类型”有什么意义?一直在看!

程序中,如下一段代码:

int arr_int[2] = {1, 2};    
pInt = arr_int;
printf("arr_int第一个元素arr_int[0]的地址是:  0X%x\n", pInt);
printf("arr_int第二个元素arr_int[1]的地址是:  0X%x\n", pInt + 1);

我将整型数组arr_int的地址赋给指针变量pInt,那么pInt的“地址”没有改变,仍然是0X22feb8,但是“值”的变化。参数变量。现在是“0X22feac”,这是 arr_int 数组的第一个元素的地址。也就是说,指针变量pInt的“地址”不会改变,但“值”可以。

现在让我们看看“pInt”和“pInt + 1”之间的区别。它使用 pInt 的“值”来执行操作。从运行结果来看,此时pInt的“值”为“0X22feac”,pInt+1的“值”为“0X22feb0”。你有没有注意到,两者之间的差别正好是4个字节,而一个“Int”数据类型也正好占用了4个字节。

你可能会认为pInt + 1使用的是“自身值”加1,所以应该是“0X22feac + 1”=“0X22fead”。为什么不?这种情况发生在指针变量 pInt 的“其他类型”上。

“其他类型”的意思,用口语来说就是:“我说pInt,兄弟,另一个值是int类型的数据值,以后如果用自己的值+1,+2,或-1、-2,但别傻了,只加1个字节或2个字节,或者只减1个字节或2个字节。int类型占用4个字节,所以需要以4个字节为单位加上1*4个字节或者2*4个字节,或者减去1*4个字节或者2*4个字节,你知道吗?无论如何,pInt + N 中的 N 可以是正数或负数。 “自值”,pInt + 2 表示“自值”加上 8 * 2 = 16 个字节,就是这个意思。

我在程序中再举一个例子来说明这个“另一种类型”。如下:

double *pDouble = NULL;
double arr_double[2] = {1.1, 2.2};
pDouble = arr_double;
printf("arr_double第一个元素arr_double[0]的地址是:  0X%x\n", pDouble);
printf("arr_double第二个元素arr_double[1]的地址是:  0X%x\n", pDouble + 1);

这次我们声明了一个指针变量pDouble,“其他类型”是“double”类型,“它自己的值”是arr_double数组的地址,“其他值”是数据值。数组元素 arr_double[0] 的“1.1”。在机器中,double类型占用8个字节,所以pDouble + 1使用pDouble“值”加1 * 8字节,pDouble + 2是pDouble的“自己的值”加2 * 8 = 16个字节,pDouble - 1是pDouble - 1 pDouble 的“自身值”减去 1 * 8 个字节,pDouble - 2 就是 pDouble 的“自身值”减去 2 * 8 = 16 个字节,我是个好孩子!小伙伴们可以根据跑步结果自己算一下吧?

3。总结

是时候总结一下了。

我做了一个指针变量声明:

type *pType = NULL;

pType有5个维度,即:

pType = (自己的地址,自己的值,其他地址,其他值,其他类型);

3.1 自地址:即“自己的地址”

作为变量,指针变量pType也有自己的地址。编写代码的常见方法是“&pType”。

地址在公共程序中不常使用。如果使用,则包含“引用指针”其他主题,本文不再讨论;

3.2 自身值:即“自身数据值”

指针变量 pType 作为变量,它也有自己的数据值,代码怎么写就是“pType”。

您还可以对值执行加法和减法运算。常见的代码编写方式有“pType + N”、“pType - N”、“pType2 - pType1”等。

3.3 其他地址:即“别人的地址”

指针变量 pType 的值,除了表示自己的数据值外,还表示与 pType 绑定的“type”类型变量的地址。一般来说,指针变量pType的“自身值”和“其他地址”是相同的数据值。

将类型type的变量绑定到pType的一般方法是:pType = &variable;

3.4 其他值:即“别人的数据值”

type类型变量与pType绑定在一起后,指针变量pType可以通过一些编写代码的方法获取type类型变量的值,即“其他价值”。常见的代码编写方式有:“*pType”、“pType->”等。

代码怎么写:“*(pType + N)”、“*(pType - N)”、“pType [N]”也是获取的“其他值”,但需要特别说明:

pType + N 可以认为是:

type *pTemp = pType + N;

" *(pType + N) "实际上计算的是指针变量pTemp的“其他值”。

" *(pType - N) " 会更容易让你理解;

“pType[N]”实际上是“*(pType + N)”,所以记住它即可。

3.5 其他类型:即“别人的类型”

声明pType指针变量时,前面的“类型”不是用来修改pType的“自己的值”,而是用来修改“其他值”。换句话说,“type”并不意味着pType的“自己的值”是type类型的数据值,而是pType的“其他值”是type类型的数据值。

代码中“其他类型”的作用主要是在计算“pType + N”和“pType - N”时为pType加减( N * sizeof(type) )个字节。

指点总是让人头晕,而且可能会让人在这五个维度中的一个或多个维度上头晕。彻底了解这5个维度。指针只是一只纸老虎。

4。练习讲解

讲解完5个维度,怎么能不开始练习呢?这里有一些练习,都与指针有关,可能会让初学者头晕。我用这5个维度来解释这个问题。看看它是多么容易!

4.1 数组元素的数量

4.1.1 程序

第一个非常常见的程序示例是查找数组元素的数量。程序如下:

示例

#include

int main(void)

{

= int *p = int LL;

in LL ; arr[3]= {1, 2, 3};

pArr = arr;

printf("数组元素:"); = 对于 0 索引 {

        printf("%d ", pArr[index]);

}

♽ ♽ ♽♽♽; for(int 索引 = 0;索引         sum = sum + *(pArr + 索引);

      }

   

    printf("数组元素个数为:%d\n", number);

  return 0;

}

这个程序非常简单。首先返回数组的所有元素,然后计算数组所有元素的总和。结果如下:

C语言指针是个纸老虎 5个方面看穿它

4.1.2 “两个自己,三个别人”的解释

4.1.2.1 输出数组元素

输出数组元素时,代码如下: ♼同理as

pArr = arr;
printf("%d ", *( pArr + index));

这里,“自身值”和“其他类型”用于执行附加操作,“其他值”用于检索数组元素。

“自己的值”:第一个代码将数组名arr中的数据值分配给pArr的“自己的值”。数组名arr的数据值是多少?就是元素arr[0]的地址,对吧!那么pArr的值也是arr[0]的地址,对吧!这样,pArr就绑定到了arr[0]。

至于(pArr + index)的含义,你可以把它看成是一个间接指针变量,pTemp:

int *pTemp = pArr + index;

也就是说,pArr + index实际上是一个pTemp指针,只不过这个pTemp是有值的。是 pArr 的值加上索引 * sizeof(int) 字节。

“其他类型”:pArr的其他类型为“int”类型,pArr+index,在pArr原值的基础上增加了多少字节? pArr的另一种类型是int类型,同样pArr + index表示pArr的值加上index * sizeof(int)字节!

pArr:可以写成pArr + 0,表示增加0 * 4 = 0个字节。此时pTemp的值就是arr[0]的地址;

pArr + 1:增加1 * 4 = 4个字节,此时pTemp的值为arr[1]的地址;

pArr + 2:即加上2 * 4 = 8字节,此时pTemp的值为arr[2]地址;

这样索引pArr+就遍历了数组所有元素的地址。

你会发现pTemp的值发生了变化; pArr 的值和地址不变。

“其他值”:由于pArr + index可以传递所有数组元素的地址,那么使用*(pArr + index),即*pTemp,可以得到其他pTemp值,所以Variable为所有数组元素的值! ?清除!

pArr + index 仍然使用pArr的值进行加法,得到临时指针pTemp的值。这个pTemp值是每个数组元素的地址;

然后使用*(pArr + inedx),即*pTemp,从临时指针pTemp中得到另一个值,即每个元素的值。

最后,将每个 pTemp 值相加即可计算数组元素的数量。? !

4.2 指针数组

指针数组是指针和数组的组合。对于初学者来说会很难理解。指针数组是一个比较大的话题。相关概念请阅读通用C语言教材。这里我们只用“二自三他”的概念来解释程序中指针的概念。

4.2.1 程序

指针数组,我举个例子如下:

Instance

#include '{void) cah *arr[3] = {"abc", "def", "ghi"};

char *pArr = arr[0];

printf("字符串数组 arr 中的每个字符串:");

for ( int index = 0;index {

"

printf("\n");

printf("字符串数组 arr 中字符串的第一个元素是: ");

for(int index = 0; index return 0;

}

运行结果如下: 4.2.2 “两人三人”的解释”

4.2.2.1 输出所有字符串

看指针数组定义:

char *arr[3] = {"abc", "def", "ghi"};

看得到的数组的每个元素,其实是这样的:

char *pChar1 = "abc", *pChar2 = "def", *pChar3 = "ghi";
char *arr[3] = {pChar1, pChar2, pChar3};

数组arr的每个元素是实际上是一个“另一种类型”的指针,即“char”。

arr[0]是指向pChar1的指针,那么pChar1的值或地址是多少?必须是字符串“abc”中字符“a”的地址,那么:

printf("%s ", arr[0]);

的意思是:

printf("%s ", pChar1);

使用另一个pChar1值或地址,从字符“a”的地址开始,输出“b”,一一下方的“c”。

pChar2 和 pChar3 也是如此。

4.2.2.2 输出第一个字符串“abc”中的每个字符

代码如下:

char *pArr = arr[0];
printf("%c ", *(pArr + index) );

给arr[0],即pChar1的值到pArr的值,然后pArr两者它自己的值和另一个地址地址字符'a'。

pArr + index 将索引 * sizeof(char) 字节添加到 pArr 的值中,给出临时指针变量 pTemp:

char *pTemp = pArr + index;

此指针 pTemp 的值或其他地址将为一:字符 'a' 的地址, 'b' , 'c',即pTemp的其他值也会依次为字符'a', 'b', 'c',所以pTemp的指针会经过字符串“abc”

4.3 链表

链表是最常用的指针,在插入节点、删除节点等操作时,你会发现自己在写下面的代码: ♽ 是这个吗?太混乱了!下一个指针就是这个,下一个指针,跳啊跳,满脑子都是粥。哈哈,5维指针分析方法已经有了!不过,关于链表,我觉得我们应该另开一篇文章来讨论一下,链表讨论完了,我们再讨论下一个指针。一旦掌握了窍门,链表就比指针更像纸老虎了。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门