指针递增运算符错误
好吧,这让我真的很困惑。 我正在解决一个硬件问题,并发现了一些对我来说非常奇怪的事情。 这是有问题的函数和调用
int find_oldest_frame(int **a, int size)
{
int min = clock();
int **ptr;
int *ptr2;
int frame = 0;
int i;
// get address of pointer so we can modify it
ptr = a;
// store off original pointer location.
ptr2 = *a;
for (i=0; i<size; i++)
{
// Who is the oldest time
if (**ptr < min)
{
min = **ptr;
frame = i;
}
printf("Current_Pointer %d\n", *ptr);
*ptr++; // For some reason ++ doesn't work.
}
// now store the oldest frame with the current system time, so it's no longer the oldest.
*ptr = ptr2;
*ptr += frame;
**ptr = clock();
*ptr = ptr2;
// Return the array index so that we can change the right page!
return frame;
}
因此,长话短说,我收到一个弹出窗口(在 Windows 中),提示存在问题并且必须关闭。
当我尝试更换时 *ptr++; 和 *ptr+=1;
程序运行。 这引起了我的兴趣,所以我在 gcc 中使用了 -S 使用 *ptr++ 版本我得到这个指令:
addl $4, -20(%ebp)
使用 *p+=1 我得到
movl -20(%ebp), %eax
movl (%eax), %eax
leal 4(%eax), %edx
movl -20(%ebp), %eax
movl %edx, (%eax)
这对我来说看起来是一个非常相似的操作,所以假设我正确地阅读了这个,
案例 1
增量 -20(%ebp) by 4 (假设 $4意味着)
情况2
我们将ebp中的内容存储到eax中,
(不确定()做什么),但是再做一次?
然后将 eax 偏移量 4 的地址加载到 edx 中,
现在再次将 ebp 复制回 eax 中,
现在将 edx 复制到 eax 中,
我的意思是看起来他们在做同样的事情,但由于某种原因 *ptr++ != * ptr+=1
为什么?我从我所看到的中错过了什么?
编辑:谢谢大家,现在我感觉很特别,我不敢相信我没有意识到这一点!
Ok so this one has me really confused.
I'm working on a HW problem, and discovered something that was really weird to me.
here is the function and call in question
int find_oldest_frame(int **a, int size)
{
int min = clock();
int **ptr;
int *ptr2;
int frame = 0;
int i;
// get address of pointer so we can modify it
ptr = a;
// store off original pointer location.
ptr2 = *a;
for (i=0; i<size; i++)
{
// Who is the oldest time
if (**ptr < min)
{
min = **ptr;
frame = i;
}
printf("Current_Pointer %d\n", *ptr);
*ptr++; // For some reason ++ doesn't work.
}
// now store the oldest frame with the current system time, so it's no longer the oldest.
*ptr = ptr2;
*ptr += frame;
**ptr = clock();
*ptr = ptr2;
// Return the array index so that we can change the right page!
return frame;
}
So to make a long story short, I get a popup (in windows) that says there was a problem and has to close.
When I try replacing
*ptr++;
with
*ptr+=1;
The program runs.
This got me interested so I used -S in gcc
With the *ptr++ version I get this instruction:
addl $4, -20(%ebp)
with *p+=1 I get
movl -20(%ebp), %eax
movl (%eax), %eax
leal 4(%eax), %edx
movl -20(%ebp), %eax
movl %edx, (%eax)
Which to me looks like a very similar operation, so assuming I'm reading this correctly,
case 1
Increment -20(%ebp) by 4 (assuming $4 means that)
case 2
we store what is in ebp to eax,
(not sure what () do), but do it again?
then take and load the address from eax offset by 4 into edx,
now copy ebp back into eax again,
now copy edx into eax,
I mean it looks like they're doing the same thing, but for some reason *ptr++ != *ptr+=1
Why? What am I missing from what I see?
EDIT: THANKS Everyone now I feel special, I can't believe I didn't realize that!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这实际上是运算符优先级的问题。后缀增量运算符在指针取消引用之前应用,这意味着您递增指针的值(它指向的内存),然后尝试取消引用它。这会调用未定义的行为,因为它指向单个
int
。在后一种情况下,
+=
在取消引用发生之后应用,因此您可以获得存储在指针内存中的值,然后添加到该值。如果您想使用后缀增量,您需要确保首先发生取消引用,您可以通过使用:而不是当前拥有的来实现。
This is actually an issue with the operator precedence. The postfix increment operator gets applied before the pointer is dereferenced, meaning that you increment the value of the pointer (the memory it points to) and then attempt to dereference it. This is invoking undefined behaviour since it points to a single
int
.In the latter case, the
+=
is applied after the dereference occurs, so you get the value stored at the pointer's memory, then you add to it. You need to make sure the dereference occurs first if you want to use postfix increment, which you can do by using:instead of what you currently have.
这
应该是
运算符优先级问题 -
*ptr++
的工作方式如下:*(ptr++)
- 与复制以 null 结尾的字符串相同的方式。
This
should be
Operator precedence matters here -
*ptr++
works this way:*(ptr++)
- the same way ascopies a null-terminated string.
运算符优先级不一样。它们分别相当于:
和:
您可以执行
*(ptr)++;
来增加指向的值并保持指针本身不变。The operator precedence is not the same. They are respectively equivalent to:
And:
You can do
*(ptr)++;
to increment the pointed value and leave the pointer itself untouched.++
运算符的优先级高于*
,其优先级高于+=
。++
绑定到ptr
,而+=
绑定到(*ptr)
。The
++
operator has higher precedence than*
, which has higher precedence than+=
. The++
binds toptr
, while the+=
binds to(*ptr)
.