指针运算的工作

时间:2016-01-07 07:22:29

标签: c pointers

main()
{
char *table[] = {"jan","feb","march"};
char **ptr =&table[1];
printf("%c",(*++*--ptr));
}

*和前缀++/--相同的优先级和R-> L关联性

**ptr的地址为feb

--ptr将转到jan地址

*--ptr取消引用ptr指向jan

++*--将指针值j增加到1

*++*--偏差高于值意味着a

我的理解是否正确?如果没有,请解释错误理解的陈述。我怀疑的是--ptr是否要转到jan或其他地址。我不确定。

3 个答案:

答案 0 :(得分:4)

如果您想确定,您应该将指令拆分为多行:

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 - 1ptr的值递减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]指向j中的jan,但在递增后,它指向a

答案 1 :(得分:2)

  

** ptr有feb的地址

这不是真的。 ptr有feb的地址。

  

- ptr将转到jan地址

这是真的。 ptr是[{1}}的地址,因此febptr-1的地址

  
      
  • 和前缀++ / - 相同的优先级和R-> L关联性
  •   

正确

答案 2 :(得分:2)

以下是我在解决这些问题时始终牢记的一些指示。

每当您在代码中看到*时(声明或乘法除外),请将其标记为value of(大声,在您的脑海中)以及每当您看到&时,请将其说成address of

现在,我只是稍微改变您的代码:

main()
{
char *table[] = {"jan","feb","march"};
char **ptr;
ptr = &table[1];
printf("%c",(*++*--ptr));
}

你的代码是正确的,我的(语法)也是如此,两者完全相同。当您在声明时初始化任何pointer时,它会按照您的方式完成,否则,在代码中的任何时候,您都不会将**附加到其中。

因此,**ptr的地址为feb - > ,因为ptr拥有它。实际上,**ptr = f,实际上是(值(((#(地址为" feb")的值)),即((" f"的地址)的值) ),即f

现在,由于ptr保留feb的地址,ptr - 1将保留jan的地址。因此,*--ptr = jan作为--ptr从其值中减去sizeof(char *),因此它将指向之前的char *,即" jan"。

现在,如果*--ptr = jan,则(*--ptr) + 1保留a的地址,当您取消引用该地址时,会为您提供a