Display bit pattern of double as hex?
up vote
2
down vote
favorite
I am trying to use printf in order to print the binary representation of a double onto the console. Here is the code that I have so far:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned long long b = *(unsigned long long *) &a;
printf("Double a = %f (0x%x)" a, b);
}
I also tried changing it from a long long to a long instead. Here is the result that I get from doing this in gcc linux:
Double a = 4.750000 (0x0)
I'm pretty sure since my system is little endian that it is only grabbing the first 32 bits which are all zeroes. However, I'm not sure how to fix this.
I thought it might have been because long is 64 bit in linux but after testing that I got the same result again. Maybe I'm printing it incorrectly? Not sure, let me know and thanks for your time.
c++ c floating-point double type-punning
|
show 1 more comment
up vote
2
down vote
favorite
I am trying to use printf in order to print the binary representation of a double onto the console. Here is the code that I have so far:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned long long b = *(unsigned long long *) &a;
printf("Double a = %f (0x%x)" a, b);
}
I also tried changing it from a long long to a long instead. Here is the result that I get from doing this in gcc linux:
Double a = 4.750000 (0x0)
I'm pretty sure since my system is little endian that it is only grabbing the first 32 bits which are all zeroes. However, I'm not sure how to fix this.
I thought it might have been because long is 64 bit in linux but after testing that I got the same result again. Maybe I'm printing it incorrectly? Not sure, let me know and thanks for your time.
c++ c floating-point double type-punning
4
Does not*(unsigned long long *) &a;violate strict aliasing?
– Sourav Ghosh
Nov 7 at 6:17
1
@SouravGhosh Yes, see What is strict aliasing
– Shafik Yaghmour
Nov 7 at 6:18
1
printf("Double a = %f (0x%llx)", a, b);
– ReAl
Nov 7 at 6:21
2
@SouravGhosh the information was for the general audience who may not understand ;-)
– Shafik Yaghmour
Nov 7 at 6:21
1
I really don't see how this is not a dupe of the strict aliasing question. If we are to keep it open, the question needs to be narrowed down to C or C++. Currently it is too broad. It would be helpful if high rep users with gold badges did an effort in moderating the cross-posting aspect of C and C++ tags before writing answers.
– Lundin
Nov 7 at 15:20
|
show 1 more comment
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I am trying to use printf in order to print the binary representation of a double onto the console. Here is the code that I have so far:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned long long b = *(unsigned long long *) &a;
printf("Double a = %f (0x%x)" a, b);
}
I also tried changing it from a long long to a long instead. Here is the result that I get from doing this in gcc linux:
Double a = 4.750000 (0x0)
I'm pretty sure since my system is little endian that it is only grabbing the first 32 bits which are all zeroes. However, I'm not sure how to fix this.
I thought it might have been because long is 64 bit in linux but after testing that I got the same result again. Maybe I'm printing it incorrectly? Not sure, let me know and thanks for your time.
c++ c floating-point double type-punning
I am trying to use printf in order to print the binary representation of a double onto the console. Here is the code that I have so far:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned long long b = *(unsigned long long *) &a;
printf("Double a = %f (0x%x)" a, b);
}
I also tried changing it from a long long to a long instead. Here is the result that I get from doing this in gcc linux:
Double a = 4.750000 (0x0)
I'm pretty sure since my system is little endian that it is only grabbing the first 32 bits which are all zeroes. However, I'm not sure how to fix this.
I thought it might have been because long is 64 bit in linux but after testing that I got the same result again. Maybe I'm printing it incorrectly? Not sure, let me know and thanks for your time.
c++ c floating-point double type-punning
c++ c floating-point double type-punning
edited Nov 7 at 6:52
Shafik Yaghmour
122k23304504
122k23304504
asked Nov 7 at 6:14
zicameau
275
275
4
Does not*(unsigned long long *) &a;violate strict aliasing?
– Sourav Ghosh
Nov 7 at 6:17
1
@SouravGhosh Yes, see What is strict aliasing
– Shafik Yaghmour
Nov 7 at 6:18
1
printf("Double a = %f (0x%llx)", a, b);
– ReAl
Nov 7 at 6:21
2
@SouravGhosh the information was for the general audience who may not understand ;-)
– Shafik Yaghmour
Nov 7 at 6:21
1
I really don't see how this is not a dupe of the strict aliasing question. If we are to keep it open, the question needs to be narrowed down to C or C++. Currently it is too broad. It would be helpful if high rep users with gold badges did an effort in moderating the cross-posting aspect of C and C++ tags before writing answers.
– Lundin
Nov 7 at 15:20
|
show 1 more comment
4
Does not*(unsigned long long *) &a;violate strict aliasing?
– Sourav Ghosh
Nov 7 at 6:17
1
@SouravGhosh Yes, see What is strict aliasing
– Shafik Yaghmour
Nov 7 at 6:18
1
printf("Double a = %f (0x%llx)", a, b);
– ReAl
Nov 7 at 6:21
2
@SouravGhosh the information was for the general audience who may not understand ;-)
– Shafik Yaghmour
Nov 7 at 6:21
1
I really don't see how this is not a dupe of the strict aliasing question. If we are to keep it open, the question needs to be narrowed down to C or C++. Currently it is too broad. It would be helpful if high rep users with gold badges did an effort in moderating the cross-posting aspect of C and C++ tags before writing answers.
– Lundin
Nov 7 at 15:20
4
4
Does not
*(unsigned long long *) &a; violate strict aliasing?– Sourav Ghosh
Nov 7 at 6:17
Does not
*(unsigned long long *) &a; violate strict aliasing?– Sourav Ghosh
Nov 7 at 6:17
1
1
@SouravGhosh Yes, see What is strict aliasing
– Shafik Yaghmour
Nov 7 at 6:18
@SouravGhosh Yes, see What is strict aliasing
– Shafik Yaghmour
Nov 7 at 6:18
1
1
printf("Double a = %f (0x%llx)", a, b);– ReAl
Nov 7 at 6:21
printf("Double a = %f (0x%llx)", a, b);– ReAl
Nov 7 at 6:21
2
2
@SouravGhosh the information was for the general audience who may not understand ;-)
– Shafik Yaghmour
Nov 7 at 6:21
@SouravGhosh the information was for the general audience who may not understand ;-)
– Shafik Yaghmour
Nov 7 at 6:21
1
1
I really don't see how this is not a dupe of the strict aliasing question. If we are to keep it open, the question needs to be narrowed down to C or C++. Currently it is too broad. It would be helpful if high rep users with gold badges did an effort in moderating the cross-posting aspect of C and C++ tags before writing answers.
– Lundin
Nov 7 at 15:20
I really don't see how this is not a dupe of the strict aliasing question. If we are to keep it open, the question needs to be narrowed down to C or C++. Currently it is too broad. It would be helpful if high rep users with gold badges did an effort in moderating the cross-posting aspect of C and C++ tags before writing answers.
– Lundin
Nov 7 at 15:20
|
show 1 more comment
3 Answers
3
active
oldest
votes
up vote
3
down vote
accepted
Your code has two issues, the simple one is that you are using the wrong format specifier %llx is the correct specifier for unsigned long long. Both clang and gcc provide a warning for this using -Wall, see it live.
The second issue is that you are violating the strict aliasing rule here:
unsigned long long b = *(unsigned long long *) &a;
the correct way to type-pun (in both C and C++) is to use memcpy (see it working live):
std::memcpy( &b, &a, sizeof(double));
At the strict aliasing link above notes in C++20 we should get bit_cast which will simplify type-punning e.g.:
b = bit_cast<unsigned long long>(a);
add a comment |
up vote
3
down vote
In C, code like
unsigned long long b = *(unsigned long long *) &a;
is illegal as it violates a rule called strict aliasing about pointers of one type referencing objects of a different type.
However, there is on exception: a char pointer may alias any object
So using char pointer, you can do something like this in C:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned char* p;
// Method 1 - direct memory read
p = (unsigned char*)&a;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", *p);
++p;
}
printf("n");
// Method 2 - reversed memory read
size_t i = sizeof(double);
p = (unsigned char*)&a + i - 1;
do
{
printf("%02x ", *p);
--p;
--i;
} while(i > 0);
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
The two methods prints with different endianness.
If you don't like pointers, you can as an alternative use a union. Like:
#include <stdio.h>
int main()
{
union
{
double a;
char c[sizeof(double)];
} d;
d.a = 4.75;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", d.c[i]);
}
printf("n");
size_t i = sizeof(double);
do
{
--i;
printf("%02x ", d.c[i]);
}
while (i > 0);
printf("n");
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
1
A minor addition: The type-punning is standard conform in C11 but not allowed in C++. You dedicated your answer to C. Hopefully, OP did notice this.
– Scheff
Nov 7 at 6:43
add a comment |
up vote
2
down vote
In C++:
double a = 4.75;
char tmp[sizeof(double)];
memcpy(tmp, &a, sizeof(double));
... // print individual bytes as hex
Alternatively:
double a = 4.75;
unsigned char* tmp = reinterpret_cast<unsigned char*>(&a);
for (int i = 0; i < sizeof(double); i++)
... // print *(tmp + i) as hex
add a comment |
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
Your code has two issues, the simple one is that you are using the wrong format specifier %llx is the correct specifier for unsigned long long. Both clang and gcc provide a warning for this using -Wall, see it live.
The second issue is that you are violating the strict aliasing rule here:
unsigned long long b = *(unsigned long long *) &a;
the correct way to type-pun (in both C and C++) is to use memcpy (see it working live):
std::memcpy( &b, &a, sizeof(double));
At the strict aliasing link above notes in C++20 we should get bit_cast which will simplify type-punning e.g.:
b = bit_cast<unsigned long long>(a);
add a comment |
up vote
3
down vote
accepted
Your code has two issues, the simple one is that you are using the wrong format specifier %llx is the correct specifier for unsigned long long. Both clang and gcc provide a warning for this using -Wall, see it live.
The second issue is that you are violating the strict aliasing rule here:
unsigned long long b = *(unsigned long long *) &a;
the correct way to type-pun (in both C and C++) is to use memcpy (see it working live):
std::memcpy( &b, &a, sizeof(double));
At the strict aliasing link above notes in C++20 we should get bit_cast which will simplify type-punning e.g.:
b = bit_cast<unsigned long long>(a);
add a comment |
up vote
3
down vote
accepted
up vote
3
down vote
accepted
Your code has two issues, the simple one is that you are using the wrong format specifier %llx is the correct specifier for unsigned long long. Both clang and gcc provide a warning for this using -Wall, see it live.
The second issue is that you are violating the strict aliasing rule here:
unsigned long long b = *(unsigned long long *) &a;
the correct way to type-pun (in both C and C++) is to use memcpy (see it working live):
std::memcpy( &b, &a, sizeof(double));
At the strict aliasing link above notes in C++20 we should get bit_cast which will simplify type-punning e.g.:
b = bit_cast<unsigned long long>(a);
Your code has two issues, the simple one is that you are using the wrong format specifier %llx is the correct specifier for unsigned long long. Both clang and gcc provide a warning for this using -Wall, see it live.
The second issue is that you are violating the strict aliasing rule here:
unsigned long long b = *(unsigned long long *) &a;
the correct way to type-pun (in both C and C++) is to use memcpy (see it working live):
std::memcpy( &b, &a, sizeof(double));
At the strict aliasing link above notes in C++20 we should get bit_cast which will simplify type-punning e.g.:
b = bit_cast<unsigned long long>(a);
edited Nov 7 at 6:48
answered Nov 7 at 6:32
Shafik Yaghmour
122k23304504
122k23304504
add a comment |
add a comment |
up vote
3
down vote
In C, code like
unsigned long long b = *(unsigned long long *) &a;
is illegal as it violates a rule called strict aliasing about pointers of one type referencing objects of a different type.
However, there is on exception: a char pointer may alias any object
So using char pointer, you can do something like this in C:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned char* p;
// Method 1 - direct memory read
p = (unsigned char*)&a;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", *p);
++p;
}
printf("n");
// Method 2 - reversed memory read
size_t i = sizeof(double);
p = (unsigned char*)&a + i - 1;
do
{
printf("%02x ", *p);
--p;
--i;
} while(i > 0);
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
The two methods prints with different endianness.
If you don't like pointers, you can as an alternative use a union. Like:
#include <stdio.h>
int main()
{
union
{
double a;
char c[sizeof(double)];
} d;
d.a = 4.75;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", d.c[i]);
}
printf("n");
size_t i = sizeof(double);
do
{
--i;
printf("%02x ", d.c[i]);
}
while (i > 0);
printf("n");
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
1
A minor addition: The type-punning is standard conform in C11 but not allowed in C++. You dedicated your answer to C. Hopefully, OP did notice this.
– Scheff
Nov 7 at 6:43
add a comment |
up vote
3
down vote
In C, code like
unsigned long long b = *(unsigned long long *) &a;
is illegal as it violates a rule called strict aliasing about pointers of one type referencing objects of a different type.
However, there is on exception: a char pointer may alias any object
So using char pointer, you can do something like this in C:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned char* p;
// Method 1 - direct memory read
p = (unsigned char*)&a;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", *p);
++p;
}
printf("n");
// Method 2 - reversed memory read
size_t i = sizeof(double);
p = (unsigned char*)&a + i - 1;
do
{
printf("%02x ", *p);
--p;
--i;
} while(i > 0);
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
The two methods prints with different endianness.
If you don't like pointers, you can as an alternative use a union. Like:
#include <stdio.h>
int main()
{
union
{
double a;
char c[sizeof(double)];
} d;
d.a = 4.75;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", d.c[i]);
}
printf("n");
size_t i = sizeof(double);
do
{
--i;
printf("%02x ", d.c[i]);
}
while (i > 0);
printf("n");
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
1
A minor addition: The type-punning is standard conform in C11 but not allowed in C++. You dedicated your answer to C. Hopefully, OP did notice this.
– Scheff
Nov 7 at 6:43
add a comment |
up vote
3
down vote
up vote
3
down vote
In C, code like
unsigned long long b = *(unsigned long long *) &a;
is illegal as it violates a rule called strict aliasing about pointers of one type referencing objects of a different type.
However, there is on exception: a char pointer may alias any object
So using char pointer, you can do something like this in C:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned char* p;
// Method 1 - direct memory read
p = (unsigned char*)&a;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", *p);
++p;
}
printf("n");
// Method 2 - reversed memory read
size_t i = sizeof(double);
p = (unsigned char*)&a + i - 1;
do
{
printf("%02x ", *p);
--p;
--i;
} while(i > 0);
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
The two methods prints with different endianness.
If you don't like pointers, you can as an alternative use a union. Like:
#include <stdio.h>
int main()
{
union
{
double a;
char c[sizeof(double)];
} d;
d.a = 4.75;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", d.c[i]);
}
printf("n");
size_t i = sizeof(double);
do
{
--i;
printf("%02x ", d.c[i]);
}
while (i > 0);
printf("n");
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
In C, code like
unsigned long long b = *(unsigned long long *) &a;
is illegal as it violates a rule called strict aliasing about pointers of one type referencing objects of a different type.
However, there is on exception: a char pointer may alias any object
So using char pointer, you can do something like this in C:
#include <stdio.h>
int main()
{
double a = 4.75;
unsigned char* p;
// Method 1 - direct memory read
p = (unsigned char*)&a;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", *p);
++p;
}
printf("n");
// Method 2 - reversed memory read
size_t i = sizeof(double);
p = (unsigned char*)&a + i - 1;
do
{
printf("%02x ", *p);
--p;
--i;
} while(i > 0);
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
The two methods prints with different endianness.
If you don't like pointers, you can as an alternative use a union. Like:
#include <stdio.h>
int main()
{
union
{
double a;
char c[sizeof(double)];
} d;
d.a = 4.75;
for (size_t i=0; i < sizeof(double); ++i)
{
printf("%02x ", d.c[i]);
}
printf("n");
size_t i = sizeof(double);
do
{
--i;
printf("%02x ", d.c[i]);
}
while (i > 0);
printf("n");
return 0;
}
Output:
00 00 00 00 00 00 13 40
40 13 00 00 00 00 00 00
edited Nov 7 at 6:45
answered Nov 7 at 6:32
4386427
19.5k21745
19.5k21745
1
A minor addition: The type-punning is standard conform in C11 but not allowed in C++. You dedicated your answer to C. Hopefully, OP did notice this.
– Scheff
Nov 7 at 6:43
add a comment |
1
A minor addition: The type-punning is standard conform in C11 but not allowed in C++. You dedicated your answer to C. Hopefully, OP did notice this.
– Scheff
Nov 7 at 6:43
1
1
A minor addition: The type-punning is standard conform in C11 but not allowed in C++. You dedicated your answer to C. Hopefully, OP did notice this.
– Scheff
Nov 7 at 6:43
A minor addition: The type-punning is standard conform in C11 but not allowed in C++. You dedicated your answer to C. Hopefully, OP did notice this.
– Scheff
Nov 7 at 6:43
add a comment |
up vote
2
down vote
In C++:
double a = 4.75;
char tmp[sizeof(double)];
memcpy(tmp, &a, sizeof(double));
... // print individual bytes as hex
Alternatively:
double a = 4.75;
unsigned char* tmp = reinterpret_cast<unsigned char*>(&a);
for (int i = 0; i < sizeof(double); i++)
... // print *(tmp + i) as hex
add a comment |
up vote
2
down vote
In C++:
double a = 4.75;
char tmp[sizeof(double)];
memcpy(tmp, &a, sizeof(double));
... // print individual bytes as hex
Alternatively:
double a = 4.75;
unsigned char* tmp = reinterpret_cast<unsigned char*>(&a);
for (int i = 0; i < sizeof(double); i++)
... // print *(tmp + i) as hex
add a comment |
up vote
2
down vote
up vote
2
down vote
In C++:
double a = 4.75;
char tmp[sizeof(double)];
memcpy(tmp, &a, sizeof(double));
... // print individual bytes as hex
Alternatively:
double a = 4.75;
unsigned char* tmp = reinterpret_cast<unsigned char*>(&a);
for (int i = 0; i < sizeof(double); i++)
... // print *(tmp + i) as hex
In C++:
double a = 4.75;
char tmp[sizeof(double)];
memcpy(tmp, &a, sizeof(double));
... // print individual bytes as hex
Alternatively:
double a = 4.75;
unsigned char* tmp = reinterpret_cast<unsigned char*>(&a);
for (int i = 0; i < sizeof(double); i++)
... // print *(tmp + i) as hex
answered Nov 7 at 6:33
Daniel Langr
6,2012244
6,2012244
add a comment |
add a comment |
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
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53184403%2fdisplay-bit-pattern-of-double-as-hex%23new-answer', 'question_page');
}
);
Post as a guest
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
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
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
4
Does not
*(unsigned long long *) &a;violate strict aliasing?– Sourav Ghosh
Nov 7 at 6:17
1
@SouravGhosh Yes, see What is strict aliasing
– Shafik Yaghmour
Nov 7 at 6:18
1
printf("Double a = %f (0x%llx)", a, b);– ReAl
Nov 7 at 6:21
2
@SouravGhosh the information was for the general audience who may not understand ;-)
– Shafik Yaghmour
Nov 7 at 6:21
1
I really don't see how this is not a dupe of the strict aliasing question. If we are to keep it open, the question needs to be narrowed down to C or C++. Currently it is too broad. It would be helpful if high rep users with gold badges did an effort in moderating the cross-posting aspect of C and C++ tags before writing answers.
– Lundin
Nov 7 at 15:20