Dereferenced union member bytes are not the same
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 = %inop.doubleNum = %fnop.floatNum = %fn", 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)
?
c memory unions
|
show 3 more comments
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 = %inop.doubleNum = %fnop.floatNum = %fn", 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)
?
c memory unions
What are you printing?
– gsamaras
Nov 24 '18 at 21:02
The int representation of each of the eight bytes stored by that union?
– tacos_tacos_tacos
Nov 24 '18 at 21:04
Are you trying to print the addresses or the values of those bytes?
– Bob__
Nov 24 '18 at 21:06
Sorry, yes the address not the values.
– tacos_tacos_tacos
Nov 24 '18 at 21:07
To print a pointer you should use the format specifier"%p"
and cast to(void *)
, but those are going to be pointers toint
, so you are not going to have the expected result either.
– Bob__
Nov 24 '18 at 21:08
|
show 3 more comments
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 = %inop.doubleNum = %fnop.floatNum = %fn", 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)
?
c memory unions
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 = %inop.doubleNum = %fnop.floatNum = %fn", 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)
?
c memory unions
c memory unions
edited Nov 24 '18 at 21:16
gsamaras
51.1k2399186
51.1k2399186
asked Nov 24 '18 at 20:59
tacos_tacos_tacostacos_tacos_tacos
5,886855107
5,886855107
What are you printing?
– gsamaras
Nov 24 '18 at 21:02
The int representation of each of the eight bytes stored by that union?
– tacos_tacos_tacos
Nov 24 '18 at 21:04
Are you trying to print the addresses or the values of those bytes?
– Bob__
Nov 24 '18 at 21:06
Sorry, yes the address not the values.
– tacos_tacos_tacos
Nov 24 '18 at 21:07
To print a pointer you should use the format specifier"%p"
and cast to(void *)
, but those are going to be pointers toint
, so you are not going to have the expected result either.
– Bob__
Nov 24 '18 at 21:08
|
show 3 more comments
What are you printing?
– gsamaras
Nov 24 '18 at 21:02
The int representation of each of the eight bytes stored by that union?
– tacos_tacos_tacos
Nov 24 '18 at 21:04
Are you trying to print the addresses or the values of those bytes?
– Bob__
Nov 24 '18 at 21:06
Sorry, yes the address not the values.
– tacos_tacos_tacos
Nov 24 '18 at 21:07
To print a pointer you should use the format specifier"%p"
and cast to(void *)
, but those are going to be pointers toint
, so you are not going to have the expected result either.
– Bob__
Nov 24 '18 at 21:08
What are you printing?
– gsamaras
Nov 24 '18 at 21:02
What are you printing?
– gsamaras
Nov 24 '18 at 21:02
The int representation of each of the eight bytes stored by that union?
– tacos_tacos_tacos
Nov 24 '18 at 21:04
The int representation of each of the eight bytes stored by that union?
– tacos_tacos_tacos
Nov 24 '18 at 21:04
Are you trying to print the addresses or the values of those bytes?
– Bob__
Nov 24 '18 at 21:06
Are you trying to print the addresses or the values of those bytes?
– Bob__
Nov 24 '18 at 21:06
Sorry, yes the address not the values.
– tacos_tacos_tacos
Nov 24 '18 at 21:07
Sorry, yes the address not the values.
– tacos_tacos_tacos
Nov 24 '18 at 21:07
To print a pointer you should use the format specifier
"%p"
and cast to (void *)
, but those are going to be pointers to int
, so you are not going to have the expected result either.– Bob__
Nov 24 '18 at 21:08
To print a pointer you should use the format specifier
"%p"
and cast to (void *)
, but those are going to be pointers to int
, so you are not going to have the expected result either.– Bob__
Nov 24 '18 at 21:08
|
show 3 more comments
3 Answers
3
active
oldest
votes
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 *)?
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. stackoverflow.com/questions/24867814/…
– 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
add a comment |
&(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.
add a comment |
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.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462317%2fdereferenced-union-member-bytes-are-not-the-same%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
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 *)?
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. stackoverflow.com/questions/24867814/…
– 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
add a comment |
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 *)?
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. stackoverflow.com/questions/24867814/…
– 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
add a comment |
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 *)?
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 *)?
edited Nov 24 '18 at 21:25
answered Nov 24 '18 at 21:16
gsamarasgsamaras
51.1k2399186
51.1k2399186
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. stackoverflow.com/questions/24867814/…
– 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
add a comment |
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. stackoverflow.com/questions/24867814/…
– 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
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
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. stackoverflow.com/questions/24867814/…
– Bob__
Nov 24 '18 at 21:24
@tacos_tacos_tacos About that, see e.g. stackoverflow.com/questions/24867814/…
– Bob__
Nov 24 '18 at 21:24
1
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
@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
add a comment |
&(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.
add a comment |
&(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.
add a comment |
&(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.
&(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.
edited Nov 24 '18 at 21:27
gsamaras
51.1k2399186
51.1k2399186
answered Nov 24 '18 at 21:19
davedave
111
111
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 24 '18 at 21:29
SG92SG92
416
416
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53462317%2fdereferenced-union-member-bytes-are-not-the-same%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What are you printing?
– gsamaras
Nov 24 '18 at 21:02
The int representation of each of the eight bytes stored by that union?
– tacos_tacos_tacos
Nov 24 '18 at 21:04
Are you trying to print the addresses or the values of those bytes?
– Bob__
Nov 24 '18 at 21:06
Sorry, yes the address not the values.
– tacos_tacos_tacos
Nov 24 '18 at 21:07
To print a pointer you should use the format specifier
"%p"
and cast to(void *)
, but those are going to be pointers toint
, so you are not going to have the expected result either.– Bob__
Nov 24 '18 at 21:08