Is this type punning well defined?
I have structure like below.
struct result{
int a;
int b;
int c;
int d;
}
and union like below.
union convert{
int arr[4];
struct result res;
}
and I type pun as below.
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1; // Here is my question, is it well defined?
printf("%d %dn", pointer->res.a, pointer->res.b);
c language-lawyer
add a comment |
I have structure like below.
struct result{
int a;
int b;
int c;
int d;
}
and union like below.
union convert{
int arr[4];
struct result res;
}
and I type pun as below.
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1; // Here is my question, is it well defined?
printf("%d %dn", pointer->res.a, pointer->res.b);
c language-lawyer
@StoryTeller I'm sorry, it typing mistake.
– KBlr
12 hours ago
2
Id you can assure no paddign in the structure - it is safe at list with gcc
– P__J__
12 hours ago
@AndyG; You're correct on the first point, but on the second, doesn't {1,2,3,5} initialise the array?
– Bathsheba
12 hours ago
1
@Bathsheba: Darn me and me illiteracy
– AndyG
12 hours ago
Hmmm, Ifstatic_assert(sizeof(convert.arr) == sizeof(convert.res), "Hmmm");was added, I think the concern about padding is gone - Code would simply not compile when padding occurred.
– chux
10 hours ago
add a comment |
I have structure like below.
struct result{
int a;
int b;
int c;
int d;
}
and union like below.
union convert{
int arr[4];
struct result res;
}
and I type pun as below.
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1; // Here is my question, is it well defined?
printf("%d %dn", pointer->res.a, pointer->res.b);
c language-lawyer
I have structure like below.
struct result{
int a;
int b;
int c;
int d;
}
and union like below.
union convert{
int arr[4];
struct result res;
}
and I type pun as below.
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1; // Here is my question, is it well defined?
printf("%d %dn", pointer->res.a, pointer->res.b);
c language-lawyer
c language-lawyer
edited 12 hours ago
AndyG
26.2k76995
26.2k76995
asked 12 hours ago
KBlrKBlr
1699
1699
@StoryTeller I'm sorry, it typing mistake.
– KBlr
12 hours ago
2
Id you can assure no paddign in the structure - it is safe at list with gcc
– P__J__
12 hours ago
@AndyG; You're correct on the first point, but on the second, doesn't {1,2,3,5} initialise the array?
– Bathsheba
12 hours ago
1
@Bathsheba: Darn me and me illiteracy
– AndyG
12 hours ago
Hmmm, Ifstatic_assert(sizeof(convert.arr) == sizeof(convert.res), "Hmmm");was added, I think the concern about padding is gone - Code would simply not compile when padding occurred.
– chux
10 hours ago
add a comment |
@StoryTeller I'm sorry, it typing mistake.
– KBlr
12 hours ago
2
Id you can assure no paddign in the structure - it is safe at list with gcc
– P__J__
12 hours ago
@AndyG; You're correct on the first point, but on the second, doesn't {1,2,3,5} initialise the array?
– Bathsheba
12 hours ago
1
@Bathsheba: Darn me and me illiteracy
– AndyG
12 hours ago
Hmmm, Ifstatic_assert(sizeof(convert.arr) == sizeof(convert.res), "Hmmm");was added, I think the concern about padding is gone - Code would simply not compile when padding occurred.
– chux
10 hours ago
@StoryTeller I'm sorry, it typing mistake.
– KBlr
12 hours ago
@StoryTeller I'm sorry, it typing mistake.
– KBlr
12 hours ago
2
2
Id you can assure no paddign in the structure - it is safe at list with gcc
– P__J__
12 hours ago
Id you can assure no paddign in the structure - it is safe at list with gcc
– P__J__
12 hours ago
@AndyG; You're correct on the first point, but on the second, doesn't {1,2,3,5} initialise the array?
– Bathsheba
12 hours ago
@AndyG; You're correct on the first point, but on the second, doesn't {1,2,3,5} initialise the array?
– Bathsheba
12 hours ago
1
1
@Bathsheba: Darn me and me illiteracy
– AndyG
12 hours ago
@Bathsheba: Darn me and me illiteracy
– AndyG
12 hours ago
Hmmm, If
static_assert(sizeof(convert.arr) == sizeof(convert.res), "Hmmm"); was added, I think the concern about padding is gone - Code would simply not compile when padding occurred.– chux
10 hours ago
Hmmm, If
static_assert(sizeof(convert.arr) == sizeof(convert.res), "Hmmm"); was added, I think the concern about padding is gone - Code would simply not compile when padding occurred.– chux
10 hours ago
add a comment |
4 Answers
4
active
oldest
votes
pointer->res.a is fine but the behaviour of pointer->res.b is undefined.
There could be an arbitrary amount of padding between the a and b members.
Some compilers allow you to specify that there is no padding between members but of course then you are giving up portability.
Thank you! If I ensure that there will be no padding is it then well defined?
– KBlr
12 hours ago
1
@KBlr: Yep! Just not portable
– AndyG
12 hours ago
3
pointer->res.aaccesses an object (arr1) through an lvalue (pointer->res) in violation of C 2018 6.5 7.
– Eric Postpischil
10 hours ago
1
@EricPostpischil So the aliasing rule applies not only to the "final" expression which is actually used to access (read or modify) an object, but to all glvalue subexpressions of the "final" expression?
– Language Lawyer
8 hours ago
1
@LanguageLawyer:struct A { int x; };andstruct B { int x; };have identical definitions but are different types. The C standard says they are not compatible, and one may not alias the other. If only theint xmattered, the aliasing rule would be useless. It is the fact that one structure cannot alias the other that enables optimization based on the aliasing rules. The aliasing rules must apply to the structures lvalues, not just theint.
– Eric Postpischil
6 hours ago
|
show 5 more comments
Is this type punning well defined?
struct result{
int a,b,c,d;
}
union convert {
int arr[4];
struct result res;
}
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1;
(union convert *) arr1 risks alignment failure.
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. C11dr §6.3.2.3 8
There is no requirement that union convert and int share the same alignment. union convert requirements may exceed int for example.
Consider this possibility: arr1 lives on int street where all addresses are multiple of 4. union and struct friends lives on "multiple of 8" street. arr1 might have address 0x1004 (not a multiple of 8).
In 2019, alignment failures are more commonly seen with char (needing 1) and other types needing 2 or more. In OP's select case, I doubt a real platform will have alignment issues, yet incorrect alignment remains possible.
This type punning is not well defined.
Additional concerns
Other answers and comments discuss padding issues, which further identifies trouble.
@Eric Postpischil comment about improper access with pointer->res.a adds more reasons to consider this UB.
add a comment |
C imposes no rule about how much padding is left between 2 consecutive members of a structure.
This is why the implementations define many #pragma directives -- specially to change this behaviour.
So, as the answer of Bathsheba says, ...->b is undefined.
I answered the very same question some time ago, here.
add a comment |
Pointer punning is not safe. Use real union punning instead.
Assumptions: the struct is properly packed (no padding between the members)
#include <stdio.h>
#include <string.h>
struct __attribute__((packed)) result{
int a;
int b;
int c;
int d;
};
union convert{
int arr[4];
struct result res;
};
volatile int arr1[4];
void foo(void)
{
union convert cnv;
memcpy(&cnv, (void *)arr1, sizeof(arr1));
printf("%d %dn", cnv.res.a, cnv.res.b);
}
all modern compilers will optimize out the memcpy call
https://godbolt.org/z/4qtRIF
.LC0:
.string "%d %dn"
foo:
mov rsi, QWORD PTR arr1[rip]
xor eax, eax
mov rdi, QWORD PTR arr1[rip+8]
mov edi, OFFSET FLAT:.LC0
mov rdx, rsi
sar rdx, 32
jmp printf
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%2f54237976%2fis-this-type-punning-well-defined%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
pointer->res.a is fine but the behaviour of pointer->res.b is undefined.
There could be an arbitrary amount of padding between the a and b members.
Some compilers allow you to specify that there is no padding between members but of course then you are giving up portability.
Thank you! If I ensure that there will be no padding is it then well defined?
– KBlr
12 hours ago
1
@KBlr: Yep! Just not portable
– AndyG
12 hours ago
3
pointer->res.aaccesses an object (arr1) through an lvalue (pointer->res) in violation of C 2018 6.5 7.
– Eric Postpischil
10 hours ago
1
@EricPostpischil So the aliasing rule applies not only to the "final" expression which is actually used to access (read or modify) an object, but to all glvalue subexpressions of the "final" expression?
– Language Lawyer
8 hours ago
1
@LanguageLawyer:struct A { int x; };andstruct B { int x; };have identical definitions but are different types. The C standard says they are not compatible, and one may not alias the other. If only theint xmattered, the aliasing rule would be useless. It is the fact that one structure cannot alias the other that enables optimization based on the aliasing rules. The aliasing rules must apply to the structures lvalues, not just theint.
– Eric Postpischil
6 hours ago
|
show 5 more comments
pointer->res.a is fine but the behaviour of pointer->res.b is undefined.
There could be an arbitrary amount of padding between the a and b members.
Some compilers allow you to specify that there is no padding between members but of course then you are giving up portability.
Thank you! If I ensure that there will be no padding is it then well defined?
– KBlr
12 hours ago
1
@KBlr: Yep! Just not portable
– AndyG
12 hours ago
3
pointer->res.aaccesses an object (arr1) through an lvalue (pointer->res) in violation of C 2018 6.5 7.
– Eric Postpischil
10 hours ago
1
@EricPostpischil So the aliasing rule applies not only to the "final" expression which is actually used to access (read or modify) an object, but to all glvalue subexpressions of the "final" expression?
– Language Lawyer
8 hours ago
1
@LanguageLawyer:struct A { int x; };andstruct B { int x; };have identical definitions but are different types. The C standard says they are not compatible, and one may not alias the other. If only theint xmattered, the aliasing rule would be useless. It is the fact that one structure cannot alias the other that enables optimization based on the aliasing rules. The aliasing rules must apply to the structures lvalues, not just theint.
– Eric Postpischil
6 hours ago
|
show 5 more comments
pointer->res.a is fine but the behaviour of pointer->res.b is undefined.
There could be an arbitrary amount of padding between the a and b members.
Some compilers allow you to specify that there is no padding between members but of course then you are giving up portability.
pointer->res.a is fine but the behaviour of pointer->res.b is undefined.
There could be an arbitrary amount of padding between the a and b members.
Some compilers allow you to specify that there is no padding between members but of course then you are giving up portability.
answered 12 hours ago
BathshebaBathsheba
176k27251374
176k27251374
Thank you! If I ensure that there will be no padding is it then well defined?
– KBlr
12 hours ago
1
@KBlr: Yep! Just not portable
– AndyG
12 hours ago
3
pointer->res.aaccesses an object (arr1) through an lvalue (pointer->res) in violation of C 2018 6.5 7.
– Eric Postpischil
10 hours ago
1
@EricPostpischil So the aliasing rule applies not only to the "final" expression which is actually used to access (read or modify) an object, but to all glvalue subexpressions of the "final" expression?
– Language Lawyer
8 hours ago
1
@LanguageLawyer:struct A { int x; };andstruct B { int x; };have identical definitions but are different types. The C standard says they are not compatible, and one may not alias the other. If only theint xmattered, the aliasing rule would be useless. It is the fact that one structure cannot alias the other that enables optimization based on the aliasing rules. The aliasing rules must apply to the structures lvalues, not just theint.
– Eric Postpischil
6 hours ago
|
show 5 more comments
Thank you! If I ensure that there will be no padding is it then well defined?
– KBlr
12 hours ago
1
@KBlr: Yep! Just not portable
– AndyG
12 hours ago
3
pointer->res.aaccesses an object (arr1) through an lvalue (pointer->res) in violation of C 2018 6.5 7.
– Eric Postpischil
10 hours ago
1
@EricPostpischil So the aliasing rule applies not only to the "final" expression which is actually used to access (read or modify) an object, but to all glvalue subexpressions of the "final" expression?
– Language Lawyer
8 hours ago
1
@LanguageLawyer:struct A { int x; };andstruct B { int x; };have identical definitions but are different types. The C standard says they are not compatible, and one may not alias the other. If only theint xmattered, the aliasing rule would be useless. It is the fact that one structure cannot alias the other that enables optimization based on the aliasing rules. The aliasing rules must apply to the structures lvalues, not just theint.
– Eric Postpischil
6 hours ago
Thank you! If I ensure that there will be no padding is it then well defined?
– KBlr
12 hours ago
Thank you! If I ensure that there will be no padding is it then well defined?
– KBlr
12 hours ago
1
1
@KBlr: Yep! Just not portable
– AndyG
12 hours ago
@KBlr: Yep! Just not portable
– AndyG
12 hours ago
3
3
pointer->res.a accesses an object (arr1) through an lvalue (pointer->res) in violation of C 2018 6.5 7.– Eric Postpischil
10 hours ago
pointer->res.a accesses an object (arr1) through an lvalue (pointer->res) in violation of C 2018 6.5 7.– Eric Postpischil
10 hours ago
1
1
@EricPostpischil So the aliasing rule applies not only to the "final" expression which is actually used to access (read or modify) an object, but to all glvalue subexpressions of the "final" expression?
– Language Lawyer
8 hours ago
@EricPostpischil So the aliasing rule applies not only to the "final" expression which is actually used to access (read or modify) an object, but to all glvalue subexpressions of the "final" expression?
– Language Lawyer
8 hours ago
1
1
@LanguageLawyer:
struct A { int x; }; and struct B { int x; }; have identical definitions but are different types. The C standard says they are not compatible, and one may not alias the other. If only the int x mattered, the aliasing rule would be useless. It is the fact that one structure cannot alias the other that enables optimization based on the aliasing rules. The aliasing rules must apply to the structures lvalues, not just the int.– Eric Postpischil
6 hours ago
@LanguageLawyer:
struct A { int x; }; and struct B { int x; }; have identical definitions but are different types. The C standard says they are not compatible, and one may not alias the other. If only the int x mattered, the aliasing rule would be useless. It is the fact that one structure cannot alias the other that enables optimization based on the aliasing rules. The aliasing rules must apply to the structures lvalues, not just the int.– Eric Postpischil
6 hours ago
|
show 5 more comments
Is this type punning well defined?
struct result{
int a,b,c,d;
}
union convert {
int arr[4];
struct result res;
}
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1;
(union convert *) arr1 risks alignment failure.
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. C11dr §6.3.2.3 8
There is no requirement that union convert and int share the same alignment. union convert requirements may exceed int for example.
Consider this possibility: arr1 lives on int street where all addresses are multiple of 4. union and struct friends lives on "multiple of 8" street. arr1 might have address 0x1004 (not a multiple of 8).
In 2019, alignment failures are more commonly seen with char (needing 1) and other types needing 2 or more. In OP's select case, I doubt a real platform will have alignment issues, yet incorrect alignment remains possible.
This type punning is not well defined.
Additional concerns
Other answers and comments discuss padding issues, which further identifies trouble.
@Eric Postpischil comment about improper access with pointer->res.a adds more reasons to consider this UB.
add a comment |
Is this type punning well defined?
struct result{
int a,b,c,d;
}
union convert {
int arr[4];
struct result res;
}
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1;
(union convert *) arr1 risks alignment failure.
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. C11dr §6.3.2.3 8
There is no requirement that union convert and int share the same alignment. union convert requirements may exceed int for example.
Consider this possibility: arr1 lives on int street where all addresses are multiple of 4. union and struct friends lives on "multiple of 8" street. arr1 might have address 0x1004 (not a multiple of 8).
In 2019, alignment failures are more commonly seen with char (needing 1) and other types needing 2 or more. In OP's select case, I doubt a real platform will have alignment issues, yet incorrect alignment remains possible.
This type punning is not well defined.
Additional concerns
Other answers and comments discuss padding issues, which further identifies trouble.
@Eric Postpischil comment about improper access with pointer->res.a adds more reasons to consider this UB.
add a comment |
Is this type punning well defined?
struct result{
int a,b,c,d;
}
union convert {
int arr[4];
struct result res;
}
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1;
(union convert *) arr1 risks alignment failure.
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. C11dr §6.3.2.3 8
There is no requirement that union convert and int share the same alignment. union convert requirements may exceed int for example.
Consider this possibility: arr1 lives on int street where all addresses are multiple of 4. union and struct friends lives on "multiple of 8" street. arr1 might have address 0x1004 (not a multiple of 8).
In 2019, alignment failures are more commonly seen with char (needing 1) and other types needing 2 or more. In OP's select case, I doubt a real platform will have alignment issues, yet incorrect alignment remains possible.
This type punning is not well defined.
Additional concerns
Other answers and comments discuss padding issues, which further identifies trouble.
@Eric Postpischil comment about improper access with pointer->res.a adds more reasons to consider this UB.
Is this type punning well defined?
struct result{
int a,b,c,d;
}
union convert {
int arr[4];
struct result res;
}
int arr1[4] = {1,2,3,5};
union convert *pointer = (union convert *) arr1;
(union convert *) arr1 risks alignment failure.
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. C11dr §6.3.2.3 8
There is no requirement that union convert and int share the same alignment. union convert requirements may exceed int for example.
Consider this possibility: arr1 lives on int street where all addresses are multiple of 4. union and struct friends lives on "multiple of 8" street. arr1 might have address 0x1004 (not a multiple of 8).
In 2019, alignment failures are more commonly seen with char (needing 1) and other types needing 2 or more. In OP's select case, I doubt a real platform will have alignment issues, yet incorrect alignment remains possible.
This type punning is not well defined.
Additional concerns
Other answers and comments discuss padding issues, which further identifies trouble.
@Eric Postpischil comment about improper access with pointer->res.a adds more reasons to consider this UB.
edited 7 hours ago
answered 9 hours ago
chuxchux
81.6k871148
81.6k871148
add a comment |
add a comment |
C imposes no rule about how much padding is left between 2 consecutive members of a structure.
This is why the implementations define many #pragma directives -- specially to change this behaviour.
So, as the answer of Bathsheba says, ...->b is undefined.
I answered the very same question some time ago, here.
add a comment |
C imposes no rule about how much padding is left between 2 consecutive members of a structure.
This is why the implementations define many #pragma directives -- specially to change this behaviour.
So, as the answer of Bathsheba says, ...->b is undefined.
I answered the very same question some time ago, here.
add a comment |
C imposes no rule about how much padding is left between 2 consecutive members of a structure.
This is why the implementations define many #pragma directives -- specially to change this behaviour.
So, as the answer of Bathsheba says, ...->b is undefined.
I answered the very same question some time ago, here.
C imposes no rule about how much padding is left between 2 consecutive members of a structure.
This is why the implementations define many #pragma directives -- specially to change this behaviour.
So, as the answer of Bathsheba says, ...->b is undefined.
I answered the very same question some time ago, here.
edited 11 hours ago
answered 12 hours ago
alinsoaralinsoar
8,12613047
8,12613047
add a comment |
add a comment |
Pointer punning is not safe. Use real union punning instead.
Assumptions: the struct is properly packed (no padding between the members)
#include <stdio.h>
#include <string.h>
struct __attribute__((packed)) result{
int a;
int b;
int c;
int d;
};
union convert{
int arr[4];
struct result res;
};
volatile int arr1[4];
void foo(void)
{
union convert cnv;
memcpy(&cnv, (void *)arr1, sizeof(arr1));
printf("%d %dn", cnv.res.a, cnv.res.b);
}
all modern compilers will optimize out the memcpy call
https://godbolt.org/z/4qtRIF
.LC0:
.string "%d %dn"
foo:
mov rsi, QWORD PTR arr1[rip]
xor eax, eax
mov rdi, QWORD PTR arr1[rip+8]
mov edi, OFFSET FLAT:.LC0
mov rdx, rsi
sar rdx, 32
jmp printf
add a comment |
Pointer punning is not safe. Use real union punning instead.
Assumptions: the struct is properly packed (no padding between the members)
#include <stdio.h>
#include <string.h>
struct __attribute__((packed)) result{
int a;
int b;
int c;
int d;
};
union convert{
int arr[4];
struct result res;
};
volatile int arr1[4];
void foo(void)
{
union convert cnv;
memcpy(&cnv, (void *)arr1, sizeof(arr1));
printf("%d %dn", cnv.res.a, cnv.res.b);
}
all modern compilers will optimize out the memcpy call
https://godbolt.org/z/4qtRIF
.LC0:
.string "%d %dn"
foo:
mov rsi, QWORD PTR arr1[rip]
xor eax, eax
mov rdi, QWORD PTR arr1[rip+8]
mov edi, OFFSET FLAT:.LC0
mov rdx, rsi
sar rdx, 32
jmp printf
add a comment |
Pointer punning is not safe. Use real union punning instead.
Assumptions: the struct is properly packed (no padding between the members)
#include <stdio.h>
#include <string.h>
struct __attribute__((packed)) result{
int a;
int b;
int c;
int d;
};
union convert{
int arr[4];
struct result res;
};
volatile int arr1[4];
void foo(void)
{
union convert cnv;
memcpy(&cnv, (void *)arr1, sizeof(arr1));
printf("%d %dn", cnv.res.a, cnv.res.b);
}
all modern compilers will optimize out the memcpy call
https://godbolt.org/z/4qtRIF
.LC0:
.string "%d %dn"
foo:
mov rsi, QWORD PTR arr1[rip]
xor eax, eax
mov rdi, QWORD PTR arr1[rip+8]
mov edi, OFFSET FLAT:.LC0
mov rdx, rsi
sar rdx, 32
jmp printf
Pointer punning is not safe. Use real union punning instead.
Assumptions: the struct is properly packed (no padding between the members)
#include <stdio.h>
#include <string.h>
struct __attribute__((packed)) result{
int a;
int b;
int c;
int d;
};
union convert{
int arr[4];
struct result res;
};
volatile int arr1[4];
void foo(void)
{
union convert cnv;
memcpy(&cnv, (void *)arr1, sizeof(arr1));
printf("%d %dn", cnv.res.a, cnv.res.b);
}
all modern compilers will optimize out the memcpy call
https://godbolt.org/z/4qtRIF
.LC0:
.string "%d %dn"
foo:
mov rsi, QWORD PTR arr1[rip]
xor eax, eax
mov rdi, QWORD PTR arr1[rip+8]
mov edi, OFFSET FLAT:.LC0
mov rdx, rsi
sar rdx, 32
jmp printf
answered 12 hours ago
P__J__P__J__
9,5912723
9,5912723
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%2f54237976%2fis-this-type-punning-well-defined%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
@StoryTeller I'm sorry, it typing mistake.
– KBlr
12 hours ago
2
Id you can assure no paddign in the structure - it is safe at list with gcc
– P__J__
12 hours ago
@AndyG; You're correct on the first point, but on the second, doesn't {1,2,3,5} initialise the array?
– Bathsheba
12 hours ago
1
@Bathsheba: Darn me and me illiteracy
– AndyG
12 hours ago
Hmmm, If
static_assert(sizeof(convert.arr) == sizeof(convert.res), "Hmmm");was added, I think the concern about padding is gone - Code would simply not compile when padding occurred.– chux
10 hours ago