Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is ptr + 1 different from ++ptr in this scenario?

Tags:

c

I originally had the following code where it is a void**:

while (it != end)
{
    *it = *(it + 1);
    it++;
}

I decided to change it + 1; it++; to ++it; because I was calculating the same value twice.

while (it != end)
{
    *it = *(++it);
}

However, after doing so, my program no longer functions the same way.

Edit: I would like to note that this is not i = i++;, but rather assigning the value pointed to by it to the value in front of it.

like image 576
Michael Smith Avatar asked Mar 07 '18 01:03

Michael Smith


People also ask

What is the difference between ptr and * ptr?

When you do: int* ptr; You are declaring a pointer of type integer named ptr. When you do: *ptr; You tell the program to point to the address stored in ptr.

What is ptr += 1 in C?

So +1 on a pointer will increment it by 4 instead of just 1. When you increment a pointer, you increment it by it's actual size and not the pointer value itself.

What does &* ptr1 mean?

ptr is a pointer and it points to some valid memory location in your case. &ptr is the address of your pointer and it can be assigned to a double pointer. int **ptr1 = &ptr; Else the address of your first element is given just by ptr .

How does parenthood tax rebate work?

The PTR can be offset against either or both your or your spouse's income tax. If the income tax payable for that YA is less than the rebate, any unutilised rebate will be carried forward to automatically be used to offset against the income tax payable for the subsequent years until the rebate has been fully utilised.


2 Answers

In *it = *(++it);, the compiler might evaluate it for the purposes of preparing the reference *it and, after that, perform the side effect of incrementing it for ++it. Or it might do the side effect first and then evaluate it for the *it. The C standard does not say in which order these must occur. The assignment itself, storing a value in *it, must be later, but that is something else. The compiler can work on parts of the left side and parts of the right side in any order it wants.

You are not allowed both modify an object (++it) and use it (in *it) without a determined order between them. Doing so results in undefined behavior. This is per C 2011 [N1570] 6.5 2:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

Incrementing it in ++it is a side effect, and using it in *it is a value computation using the value of it, which is a scalar object. Therefore, the behavior is undefined.

like image 70
Eric Postpischil Avatar answered Jan 02 '23 06:01

Eric Postpischil


C99, 6.5 Expressions:

  1. Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

(Emphasis mine.)

In

*it = *(++it);

We read twice and store once. *it on the left side reads from it; ++it on the right side reads from and stores to it. There are no sequences points here.

This expression has undefined behavior because the read on the left side is not used to determine the value to be stored.

*it = *(it + 1); is allowed because it is not modified here (there are no stores), so you can have as many reads as you want.

like image 39
melpomene Avatar answered Jan 02 '23 06:01

melpomene