繁体   English   中英

指针算法的工作

[英]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] (或tablechar **的衰减值)。

第二条指令是*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] ,因此*ptrtable[0]所以当您执行*ptr = *ptr + 1; ,您增加了table[0]

刚开始时, table[0]指向janj ,但递增后,它指向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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM