1

From the tutorial at learnc, I am experimenting with some really basic stuff on pointers and unions. In the code below I create a struct operator with an anonymous union consisting of a float, double, and int. Since double is the biggest one at eight bytes, I expect to see my int have eight bytes, which it does. However, they are not the same bytes as the double!

typedef enum {
    INTEGER = 0,
    FLOAT = 1,
    DOUBLE = 2,
} operator_type;

typedef struct operator {
    operator_type type;

    union {
        int intNum;
        double doubleNum;
        float floatNum;
    };
} operator_t;

int main() {

    operator_t op;
    op.type = FLOAT;
    op.floatNum = 3.14f;

    printf("op.intNum = %i\nop.doubleNum = %f\nop.floatNum = %f\n", op.intNum, op.doubleNum, op.floatNum);

    printf("op.intNum [%i, %i, %i, %i, %i, %i, %i, %i, %i]",
           &(op.intNum) + 0,
           &(op.intNum) + 1,
           &(op.intNum) + 2,
           &(op.intNum) + 3,
           &(op.intNum) + 4,
           &(op.intNum) + 5,
           &(op.intNum) + 6,
           &(op.intNum) + 7,
           &(op.intNum) + 8
           );

    printf("op.doubleNum [%i, %i, %i, %i, %i, %i, %i, %i, %i]",
           &(op.doubleNum) + 0,
           &(op.doubleNum) + 1,
           &(op.doubleNum) + 2,
           &(op.doubleNum) + 3,
           &(op.doubleNum) + 4,
           &(op.doubleNum) + 5,
           &(op.doubleNum) + 6,
           &(op.doubleNum) + 7,
           &(op.doubleNum) + 8
    );

    return 0;
}

I get the output:

op.intNum [-13304, -13300, -13296, -13292, -13288, -13284, -13280, -13276, -13272]
op.doubleNum [-13304, -13296, -13288, -13280, -13272, -13264, -13256, -13248, -13240]

Shouldn't &(op.intNum) == &(op.doubleNum) == &(op.floatNum) ?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
tacos_tacos_tacos
  • 10,277
  • 11
  • 73
  • 126

3 Answers3

1

Shouldn't &(op.intNum) == &(op.doubleNum) == &(op.floatNum)?

Yes, they should, and they are.

In order to print an address, use %p as the format specifier, and cast it to void*. Read more in How to print variable addresses in C?

Edit: Why do I have to cast my memory address to (void *)?

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • So one more quick question ... actually, casting them to `(void *)` is what made them have the same output, the output format might have been nonsense because of the `%i`, but it is interesting to me still that the `(void *)` cast is necessary. – tacos_tacos_tacos Nov 24 '18 at 21:21
  • @tacos_tacos_tacos About that, see e.g. https://stackoverflow.com/questions/24867814/printfp-and-casting-to-void – Bob__ Nov 24 '18 at 21:24
  • 1
    @tacos_tacos_tacos I posted a duplicated of Bob. Pointers *can* have different representations, so they need to be casted into something generic.. – gsamaras Nov 24 '18 at 21:26
1

&(op.intNum) + 1 is the address immediately after the end of op.intNum.

That is, if op.intNum is at address A, and sizeof op.intNum is 4, then the expression you wrote has value A+4.

That's a consequence of how pointer arithmetic is defined.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
dave
  • 11
  • 1
0

In your case you don't dereference union, for dereferencing you need to declare op as pointer.

FYI:

In your code you print

  • address of int member, and sizeof(int) is 4 in your architecture, so increment by 1 , your address will be address + sizeof(int)

  • address of double member and sizeof(double) in 8, in this case each after each increment your address will be address + 8

Hope this will help.

SG92
  • 76
  • 9