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;