nalostta
nalostta

Reputation: 43

How to explain the following code's output? (related to typecasting in C)

I came across this code snippet from a blog who was asking for it's output and an explanation.

#include<stdio.h>

int main()
{
    int *const volatile p = 5;
    printf("%d\n",5/2+p);
    return 0;
}

Here's what I understand so far:

1.The const and volatile keywords don't contribute in context of the output

2.This code is a bad one as it performs arithmetic operation between an int* and an int without a proper cast.

3.I initially assumed the output should be undefined. The blog stated the answer to be 13 (which what i experimentally found).

Q.What I don't understand is how was 13 obtained, was it the outcome of an undefined behavior from the compiler?

4.I used gdb and determined that the crux lies in the operation p+2 , where p is the pointer (holding value 5) and 2 is the outcome of integer division (5/2).

Upvotes: 1

Views: 452

Answers (3)

It is undefined behavior indeed, but not due to the arithmetic. Due to the wrong conversion specifier to print a pointer - %d instead of %p with an argument cast to void * - and to initialize a pointer by an non-zero int value.

To the arithmetic itself:

If the size of an int is 4/ sizeof(int) == 4 (as it seems to be on your platform) the result is 13 because you increment the pointer value by 2.

You increment by 2 because at 5/2 is happening integer arithmetic and the fraction part of 2.5 will be discarded.

When starting from 5, it adds 2 4er steps.

sizeof(int) == 4
5 + (sizeof(int) * 2) == 13

OR

5 + 8 = 13.

But as said above, it is undefined behavior due to the wrong conversion specifier and to assign a pointer by an non-zero int value.


For the integer initialization of the pointer:

"Pointer from integer/integer from pointer without a cast" issues

For the wrong conversion specifier:

How to print the address value of a pointer in a C program?

Upvotes: 4

Confidenc3
Confidenc3

Reputation: 706

Depending on the fact that the sizeof(int) == 4, then the command

int *const volatile p = 5;

assigns to the pointer, as initial address, (something like) 0x0005 5 is not a value, but the address, as you have not allocated some memory for it. Then, on the result of printf(), the result is 2+p, which means pointer arithmetics. The pointer is of type int, therefore, you add on its address 2 positions away. Thus, 2 sizeof(int) further is 2 * 4 = 8. Conclusively, the address where the pointer points is 5+8 = 13. For example, you can remove the keywords volatile and const to understand that they do not affect the result. Also, you print out the address where the pointer refers, but not the subject of it(or the result of de-referencing to that address)

Upvotes: 1

M.M
M.M

Reputation: 141648

This code is incorrect:

int *const volatile p = 5;

An integer cannot be assigned to (or initialize, the rules are the same) a pointer, except for the special case of a constant expression of zero value . The compiler must give a diagnostic and can reject the program. And if it does generate an executable anyway, the language rules no longer apply since the code broke the contract.

This code is a bad one as it performs arithmetic operation between an int* and an int without a proper cast.

You are allowed to add an integer and a pointer without a cast. In fact that is normal practice. It means that you advance the pointer by that number of elements of what it is pointing to.

Notwithstanding the above though, pointer arithmetic must stay within the bounds of an array object, or point one-past-the-end. (Non-arrays can be treated as arrays of size 1 for this purpose). So the validity of 5/2 + p, i.e. p + 2, would depend on whether p was already pointing into an array and there was another array element after it at least. In your exact program it's moot since the program is invalid.

Similarly, the question of the printf is also moot since we already ran off the rails. But the operand for %d must have type int (it cannot be a pointer).

Upvotes: 4

Related Questions