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
或其他地址。我不确定。
答案 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 - 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]
指向j
中的jan
,但在递增后,它指向a
。
答案 1 :(得分:2)
** ptr有feb的地址
这不是真的。 ptr有feb
的地址。
- ptr将转到jan地址
这是真的。 ptr
是[{1}}的地址,因此feb
是ptr-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
。