2

I'm having trouble understanding the following code:

char arr[] = {0,1,2,3};
void *vp;
int *ip;

vp = arr; 
ip = vp; 

How is it possible that the int pointer ip can point to an element of arr if the array itself it's char? As I understand, while defining the pointer it must the same type as the data it poins to, but why in this case is it possible?

EduHG
  • 31
  • 4
  • 2
    You can convert any pointer type to another pointer type. But dereferencing the resulting pointer won't be meaningful. – Barmar Feb 09 '23 at 18:01
  • 3
    Since you never dereference `ip` in this code, there's nothing wrong. But if you try to do `printf("%d", *ip);` the result is either undefined or implementation-defined, I'm not sure which. – Barmar Feb 09 '23 at 18:02
  • Merely creating an `int *` pointer from the address of a `char` object can invoke undefined behavior. Per [**6.3.2.3 Pointers**, paragraph 7 of the (draft) C11 standard](https://port70.net/~nsz/c/c11/n1570.html#6.3.2.3p7): "A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined." – Andrew Henle Feb 09 '23 at 18:09
  • And if you were to then *dereference* that `int *` pointer and access the `char` array as if it were an `int`, you would be violating [strict aliasing](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) – Andrew Henle Feb 09 '23 at 18:09
  • @Barmar *Since you never dereference `ip` in this code, there's nothing wrong.* Not true. If `arr` is not correctly aligned for an `int`, merely putting the address of `arr` in `ip` invokes undefined behavior. – Andrew Henle Feb 09 '23 at 18:10
  • Since this may cause undefined behavior, the compiler is not required to diagnose it. So you can do this without any compilation errors. A smart compiler may detect the problem and issue a warning, but it's not required. – Barmar Feb 09 '23 at 18:13

3 Answers3

2

How is it possible that the int pointer ip can point to an element of arr if the array itself it's char?

It is not possible. The code presented is valid, but the effect is not to store in ip a pointer to any element of array arr. By definition, ip points to an int, and the elements of arr are not ints, so ip does not point to any of them.

As I understand, while defining the pointer it must the same type as the data it poins to, but why in this case is it possible?

Because pointer values are not necessarily valid (for their types, or even generally). The result of the code presented is not that ip points to a char, but that attempting to dererference its value produces undefined behavior. The same would be true after ip = NULL;, though the undefined behavior resulting from evaluating *ip would likely be different in the two cases.

You can characterize that as ip not pointing to anything, though I suppose you will recognize that that's an incomplete description. The effect of ip = vp is generally not the same as that of ip = NULL.

More broadly, it is essential to understand that pointers are their own kind of values, distinct from and not inherently connected to the objects, if any, to which they point.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
1

This code

char arr[] = {0,1,2,3};
void *vp;
int *ip;

vp = arr; 
ip = vp; 

can invoke undefined behavior as it is.

Per 6.3.2.3 Pointers, paragraph 7 of the (draft) C11 standard (bolding mine):

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.

Note that no dereference of the pointer is necessary - merely creating a misaligned pointer invokes undefined behavior.

Since there's no guarantee that arr is properly aligned for an int value, undefined behavior can not be ruled out.

And if you were to actually dereference ip and access arr as if it were an int value, that would be violating strict aliasing and would always be undefined behavior.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
1

This code does "pointer punning". It is one of the way of using the binary representation of one type as another type.

In C it violates the strict alising rules and it is Undefined Behavior.

In your case (assuming 4 bytes int) the content of the char array is going to be interpreted as int value.

int main(void)
{
    char arr[] = {0,1,2,3};
    int *ip = (int *)arr;

    printf("%d - 0x%08x\n", *ip, *ip);

}

output

50462976 - 0x03020100

The hex value is easier to interpret as two digits of the number represent one byte in the memory. As you see the the number is "reversed" comparing to the representation in the memory. It is because PC computers are little endian and least significant byte is store first. https://en.wikipedia.org/wiki/Endianness

To avoid Undefined Behavior you should copy the array into the integer

int main(void)
{
    char arr[] = {0,1,2,3};
    int ip;

    memcpy(&ip, arr, sizeof(ip));
    printf("%d - 0x%08x\n", ip, ip);
}

How is it possible that the int pointer ip can point to an element of arr if the array itself it's char?

In the end, any object (it does not matter what its type is) is just a bunch of chars (bytes) stored in the memory. Your pointer is referencing some location in memory.

0___________
  • 60,014
  • 4
  • 34
  • 74