C 指针算法的工作原理
C 指针算法的工作原理,c,pointers,C,Pointers,*和前缀++/--具有相同的优先级和R->L关联性 **ptr的地址为feb --ptr将转到jan地址 *--ptr取消引用ptr指向jan ++*--将指针值j增加到1 *++*--高于该值表示a 我的理解正确吗?如果没有,请解释错误的理解陈述。我的疑问是--ptr是否转到jan的地址或其他地址。我不确定 **ptr的地址是二月 那不是真的。ptr的地址为feb --ptr将转到1月的地址 没错ptr是feb的地址,所以ptr-1是jan 和前缀++/--相同的优先级和R->L关联性 正
*
和前缀++/--
具有相同的优先级和R->L关联性
**ptr
的地址为feb
--ptr
将转到jan
地址
*--ptr
取消引用ptr
指向jan
++*--
将指针值j
增加到1
*++*--
高于该值表示a
我的理解正确吗?如果没有,请解释错误的理解陈述。我的疑问是--ptr
是否转到jan
的地址或其他地址。我不确定
**ptr的地址是二月
那不是真的。ptr的地址为feb
--ptr将转到1月的地址
没错ptr
是feb
的地址,所以ptr-1
是jan
- 和前缀++/--相同的优先级和R->L关联性
正确在解决这类问题时,我总是牢记以下几点 每当你在代码中看到
*
(声明或乘法除外),就把它说成的值(大声,在你的脑袋里),每当你看到和时,就把它说成的地址
现在,我只是稍微修改一下您的代码:
main()
{
char *table[] = {"jan","feb","march"};
char **ptr =&table[1];
printf("%c",(*++*--ptr));
}
你的代码是正确的,我的(语法上)也是正确的,两者完全相同。当您在声明时初始化任何指针
时,它将按您所做的那样完成,否则,在代码中的任何时间,您都不会将**
附加到它
所以,**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
,如果您想确保:
char*表[]={“一月”、“二月”、“三月”};
字符**ptr=&表[1];
//这:
*++*--ptr;
//同:
ptr=ptr-1;//前缀--
*ptr=*ptr+1;//*--ptr上的前缀+
**ptr;
因为您知道所有运算符的优先级,所以可以很容易地做到这一点,现在它更具可读性
理解此时发生的情况的一种方法是查看内存的外观(假设sizeof(void*)==2,并且所有指针类型都具有相同的sizeof
):
第一条指令是ptr=ptr-1
,因为ptr
属于char**
类型,ptr-1
将ptr
的值递减sizeof(*ptr)
(即sizeof(char*)
)。因此,在我们的示例中,ptr
将被2
递减:
// 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
包含表[0]
(或者表
到字符**
的衰减值)
第二条指令是*ptr=*ptr+1
,因此您要增加ptr
所指的值,该值是存储在地址0x8742
处的值,该地址是表的第一个单元格
0x8844: 0x8742 // after --ptr
您将*ptr
的值增加了多少?通过sizeof(**ptr)
,即sizeof(char)
(在本例中假设1
),可以得到0x1242=0x1241+1
最后,第三条指令是简单的**ptr
,因此首先获取ptr
所指地址处的值(即0x1242
),然后获取该地址处的值,即'a'
额外…如果您想检查您对上述内容的理解,您应该考虑以下输出(在原始printf
之前和之后):
在这之前,你会得到一月(正如预期的那样),但是在这之后
这将只输出an
(而不是jan
)。为什么?因为当您执行+*--ptr
时,这与:
printf("%s", table[0]);
您修改了ptr
所指的值。这个值是多少?嗯,在ptr=ptr-1之后
,ptr
指向&表[0]
,所以*ptr
是表[0]
所以当您执行*ptr=*ptr+1代码>,您增加了表[0]
开始时,表[0]
指向jan
中的j
,但递增后,它指向a
您是否尝试过查看发生了什么?是的。你几乎是对的<代码>**ptr
的地址是feb
应该是ptr
的地址是feb
。当然@gr我试图理解这就是为什么我解释了这些步骤,但我不确定我问这个问题的原因是对是错。@haccks感谢您的回答。我同意你的看法。但是--ptr
是指jan
的地址吗?我想的是,如果我们做--ptr
,ptr
的地址是递减的,而不是feb
的地址。因此,它将如何到达地址jan
?--ptr
从它的值中减去sizeof(char*)
,因此它将指向前面的char*
,即“jan”
。我在写答案时想到了这一点::D:dt感谢您的精彩答案--ptr从它的值中减去sizeof(char*),所以
0x8742: 0x1242 0x1542 0x171
printf("%s", table[0]);
ptr = ptr - 1;
*ptr = *ptr + 1;