2

So I'm learning about C pointers, and I'm a little confused. Pointers just point to specific memory address.

sizeof(char*), sizeof(int*), sizeof(double*) all output 8. So they all take 8 bytes to store a memory address.

However, if I try to compile something like this:

int main(void)
{
    char letter = 'A';
    int *a = &letter;
    printf("letter: %c\n", *a);
}

I get a warning from the compiler (gcc):

 warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
     int *a = &letter;

However, char *a = &letter;, doesn't result in a warning.

Why does the type of the pointer matter, if it's 8 bytes long anyway? Why does declaring a pointer with a type different than the type of data it's pointing to yield in a warning?

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
bool3max
  • 2,748
  • 5
  • 28
  • 57
  • 2
    It's the type of the thing that you are pointing to that matters, and a `char` is not an `int`. – Ken Y-N Nov 16 '17 at 00:32
  • 1
    a) type safety/nice compilation warnings b) [the size of pointer types aren't guaranteed to be equal](https://stackoverflow.com/questions/399003/is-the-sizeofsome-pointer-always-equal-to-four). – hnefatl Nov 16 '17 at 00:32
  • Don't generalize from the behavior of your implementation and make assumptions about C in general. On most implementations, pointers are the same size -- but not all. – Keith Thompson Nov 16 '17 at 00:34
  • 2
    How many bytes would `*pointer = 42;` change? Should 42 be represented as a floating-point number or not? The compiler has no way to know that without the pointer types. – HolyBlackCat Nov 16 '17 at 00:40

3 Answers3

6

The issue isn't about the size of the pointer - it's about the type of the pointee.

If you have a pointer to an int, the pointer takes up some number of bytes (seems like you have a 64-bit system, where that pointer takes up eight bytes). However, if you dereference that pointer to read or write what it points to, because the type of the pointer is int*, the read or write will try to manipulate sizeof(int) bytes at the target, and it will try to manipulate them as though they're an int.

If you have a single object of type char, which by definition has size 1, and you try to read or write it through a pointer of type int, which (on many systems) has size 4, then reading the pointer will pull back some garbage data along with the char and writing to the pointer will clobber random regions of memory around that char with unrelated values.

Additionally, C has a rule called the strict aliasing rule that says that you are not allowed to read or write through a pointer of a type that doesn't match the type of what's being pointed at (unless the pointer is of type char *, signed char*, or unsigned char*). Breaking strict aliasing can mess up all sorts of compiler optimizations and lead to code that doesn't behave as expected.

So in short, the size of the pointer really isn't the issue here. It's the semantics about what happens when you try to read or write what's being pointed at.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • Thank you! I understand it perfectly now. And sure, I tried a `char*` pointer to an `int` larger than 255, and it printed the wrong value. Thank you! – bool3max Nov 16 '17 at 00:45
2

Think about what you're going to do with the pointer.

int n = 42;
char *p = &n; // BAD

If this compiles (a compiler can reject it outright rather than printing a non-fatal warning), you have a pointer that points to the memory occupied by the int object n. How are you going to get the value of that object? *p gives you a char result, most likely the first byte of n -- which may be the high-order byte or the low-order byte.

Pointer types depend on the type of object they point to so that you can access that object.

(Also, don't make assumptions based on the behavior of your particular implementation. 32-bit systems have 4-byte pointers, and the language doesn't guarantee that all pointers are the same size.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

It's not about bytes length but about the type of what you're pointing to. Char and int are completly different. Moreover, sizeof(char) equal 1 and sizeof(int *) equal 8.

Nicolas Guerin
  • 356
  • 2
  • 18