[英]Working of pointer arithmetic
main()
{
char *table[] = {"jan","feb","march"};
char **ptr =&table[1];
printf("%c",(*++*--ptr));
}
*
和前缀++/--
相同的优先级,并且R-> L关联性
**ptr
地址为feb
--ptr
将转到jan
地址
*--ptr
取消引用指向jan
ptr
++*--
指针值j
增加到1
*++*--
高于该值表示a
我的理解正确吗? 如果没有,请解释错误的理解的陈述。 我的疑问是--ptr
转到jan
地址还是其他某个地址。 我不确定。
如果要确保,请在多行上拆分指令:
char *table[] = {"jan","feb","march"};
char **ptr = &table[1];
// This:
*++*--ptr;
// Is the same as:
ptr = ptr - 1; // prefix --
*ptr = *ptr + 1; // prefix ++ on *--ptr
**ptr;
由于您知道所有运算符的优先级,因此可以轻松地做到这一点,现在它更具可读性。
了解此时发生情况的一种方法是查看内存的外观(假设sizeof(void*) == 2
,并且所有指针类型都具有相同的sizeof
):
// Somewhere in the rodata segment (these are probably contiguous, but I don't really care).
// The 0 are for the null character at the end.
0x1241: jan0
0x1542: feb0
0x1712: march0
// Somewhere in your stack
0x8742: 0x1241 0x1542 0x171 // This is table (contiguous)
0x8844: 0x8744 // This is ptr
所述第一指令是ptr = ptr - 1
,由于ptr
的类型是char **
, ptr - 1
将要减小的值ptr
通过sizeof(*ptr)
这是sizeof(char*)
因此,在我们的示例中, ptr
将减少2
:
0x8844: 0x8742 // after --ptr
您清楚地看到ptr
包含&table[0]
(或table
对char **
的衰减值)。
第二条指令是*ptr = *ptr + 1
,因此您将增加ptr
指向的值,该值是存储在地址0x8742
的值(在我们的示例中),该地址是table
的第一个单元格:
0x8742: 0x1242 0x1542 0x171
您将*ptr
的值增加了多少? 好吧,通过sizeof(**ptr)
,它是sizeof(char)
(在此示例中假设为1
),因此您得到0x1242 = 0x1241 + 1
。
最后,第三条指令就是**ptr
,所以您首先在ptr
指向的地址(即0x1242
)处获取值,然后在该地址处获取值'a'
。
额外...如果您想了解一下以上内容,您应该考虑以下输出(原始printf
之前和之后):
printf("%s", table[0]);
之前,您将获得jan
(如预期的那样),但之后...
这将仅输出an
(而不是jan
)。 为什么? 因为当您执行++*--ptr
,它与:
ptr = ptr - 1;
*ptr = *ptr + 1;
您修改了ptr
指向的值。 这个值是多少? 好吧,在ptr = ptr - 1;
, ptr
指向&table[0]
,因此*ptr
是table[0]
所以当您执行*ptr = *ptr + 1;
,您增加了table[0]
。
刚开始时, table[0]
指向jan
的j
,但递增后,它指向a
。
** ptr的地址为2月
这不是真的。 ptr的地址是feb
。
--ptr将转到jan地址
确实如此。 ptr
是ADRESS feb
所以ptr-1
是ADRESS jan
- 和前缀++ /-相同的优先级和R-> L关联性
正确
在解决这些问题时,我始终牢记一些提示。
每当在代码中看到*
时(声明或乘法除外),都将其value of
(大声,在您的头脑中)的值,每当看到&
,将其表示为的address of
。
现在,我只是稍微更改一下代码:
main()
{
char *table[] = {"jan","feb","march"};
char **ptr;
ptr = &table[1];
printf("%c",(*++*--ptr));
}
您的代码是正确的,我的(语法上)也是正确的,并且两者完全相同。 当您在声明时初始化任何pointer
时,它会按您的方式完成,否则,在代码的任何以后的任何时候,您都不会在其上附加**
。
因此, **ptr
地址为feb
> NO ,因为ptr
拥有它。 实际上, **ptr = f
,实际上是(value at(value at(“ fb”的地址)))),也就是(value at(value(“ f”的地址))),即f
。
现在,由于ptr
拥有feb
地址,因此ptr - 1
将拥有jan
地址。 因此, *--ptr = jan
因为--ptr
从其值中减去sizeof(char *)
,因此它将指向前一个char *
,即“ jan”。
现在,如果*--ptr = jan
,那么, (*--ptr) + 1
持有的地址a
,这时候你取消对它的引用,给你a
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.