Is this proper?
Author |
Message |
DtY
|
Posted: Wed Sep 16, 2009 6:18 pm Post subject: Is this proper? |
|
|
c: | #include <stdlib.h>
#include <stdio.h>
#define makeChrArray(a) (char *)(&a)
int main (void) {
int myNum = 12345;
char *mc;
mc = makeChrArray (myNum );
printf("%d %d %d %d\n",mc [0], mc [1], mc [2], mc [3]);
myNum++;
printf("%d %d %d %d\n",mc [0], mc [1], mc [2], mc [3]);
return 0;
} |
It casts an integer to an array of characters, so each can be accessed individually, or written to a file (which I don't think you can just do with an integer, can you? (without converting to decimal))
I know there's a function that does something similar (I can't remember the name, and can't find it with google), however it requires you to allocate the necessary memory for it, so unless you need to capture it, change it, and get it as a character array again, you're doing a lot of extra steps.
This, compiles fine with GCC, but I have no idea if it's guaranteed to work, it feels pretty hackish. (And of course, it's endianess specific, I believe the other function allowed you to specify the endianess to use, it also expects an int to be 32 bit, so I were to use this, I'd probably want to use sizeof(int) and a loop).
[edit] It also (of course) returns the expected numbers |
|
|
|
|
|
Sponsor Sponsor
|
|
|
DemonWasp
|
Posted: Wed Sep 16, 2009 6:33 pm Post subject: RE:Is this proper? |
|
|
That's pretty much what's expected in C / C++. It's endian-specific, but if you're concerned about that, you can record everything in network byte order using htons, htonl, ntohs, ntohl, which convert host to network short/long and vice-versa. |
|
|
|
|
|
wtd
|
Posted: Thu Sep 17, 2009 2:01 am Post subject: RE:Is this proper? |
|
|
If you can assume C99, you may wish to use the stdint.h header to be sure on the size of int types.
There's a simple way to test for endianness.
code: | int is_little_endian()
{
unsigned int n = 1;
return *(char *)n;
} |
|
|
|
|
|
|
OneOffDriveByPoster
|
Posted: Fri Sep 18, 2009 8:38 am Post subject: Re: Is this proper? |
|
|
DtY @ Wed Sep 16, 2009 6:18 pm wrote: This, compiles fine with GCC, but I have no idea if it's guaranteed to work, it feels pretty hackish. Given your assumptions that int is 4 bytes, this is guaranteed to work. This is a special case of accessing data as a "char" (and similar) as opposed to accessing it as what it is. If you had a char array and put in a representation of an int into it, do not expect to see the int value when you access that memory through an int*. |
|
|
|
|
|
DemonWasp
|
Posted: Fri Sep 18, 2009 11:02 am Post subject: RE:Is this proper? |
|
|
You can do this with the "union" feature as well:
code: |
union my_int {
int n;
char[4] b;
}
my_int test;
test.n = 12345;
printf("%d %d %d %d\n", test.b[0], test.b[1], test.b[2], test.b[3]);
test.n++;
printf("%d %d %d %d\n", test.b[0], test.b[1], test.b[2], test.b[3]);
|
Note that I haven't tested the above and I may have my syntax wrong, but I think that should work. |
|
|
|
|
|
DtY
|
Posted: Fri Sep 18, 2009 2:57 pm Post subject: Re: Is this proper? |
|
|
OneOffDriveByPoster @ Fri Sep 18, 2009 8:38 am wrote: DtY @ Wed Sep 16, 2009 6:18 pm wrote: This, compiles fine with GCC, but I have no idea if it's guaranteed to work, it feels pretty hackish. Given your assumptions that int is 4 bytes, this is guaranteed to work. This is a special case of accessing data as a "char" (and similar) as opposed to accessing it as what it is. If you had a char array and put in a representation of an int into it, do not expect to see the int value when you access that memory through an int*.
Really? Why wouldn't it work?
wtd @ Thu Sep 17, 2009 2:01 am wrote: If you can assume C99, you may wish to use the stdint.h header to be sure on the size of int types.
There's a simple way to test for endianness.
code: | int is_little_endian()
{
unsigned int n = 1;
return *(char *)n;
} |
Thanks. Is there any way to test for endianess at compile time? |
|
|
|
|
|
DemonWasp
|
Posted: Fri Sep 18, 2009 6:36 pm Post subject: RE:Is this proper? |
|
|
My example code won't execute, but this will:
c: |
#include <stdio.h>
using namespace std;
typedef union my_int {
int n;
char b [4];
};
int main ( int argc, char ** argv ) {
union my_int test = { 12345 };
printf ( "%X\n", test. n );
printf ( "%X %X %X %X\n", test. b[0], test. b[1], test. b[2], test. b[3] );
++test. n;
printf ( "%X %X %X %X\n", test. b[0], test. b[1], test. b[2], test. b[3] );
}
|
On my little-endian x86-64 CPU, that results in:
code: |
3039
39 30 0 0
3A 30 0 0
|
Note the reversed byte order between the way the 4-byte integer is output and the way the 1-byte chars are output - that's little endian.
Determining endianness at compile-time seems to come down to compiling and running a file to find endianness, then using its output to #define or #include things as you wish. There may also be non-portable ways for each of the (many) compilers out there. |
|
|
|
|
|
DtY
|
Posted: Fri Sep 18, 2009 8:37 pm Post subject: Re: RE:Is this proper? |
|
|
DemonWasp @ Fri Sep 18, 2009 6:36 pm wrote: My example code won't execute, but this will:
--snip--
Note the reversed byte order between the way the 4-byte integer is output and the way the 1-byte chars are output - that's little endian.
Determining endianness at compile-time seems to come down to compiling and running a file to find endianness, then using its output to #define or #include things as you wish. There may also be non-portable ways for each of the (many) compilers out there.
Okay, thanks. Shame you can't (really) test at compile time, it seems like something that should have come up when C was being standardized.
Oh well, I guess if I ever write a program that depends on endianess, I can just add all that stuff in the makefile. |
|
|
|
|
|
Sponsor Sponsor
|
|
|
OneOffDriveByPoster
|
Posted: Fri Sep 18, 2009 9:16 pm Post subject: Re: Is this proper? |
|
|
DtY @ Fri Sep 18, 2009 2:57 pm wrote: OneOffDriveByPoster @ Fri Sep 18, 2009 8:38 am wrote: DtY @ Wed Sep 16, 2009 6:18 pm wrote: This, compiles fine with GCC, but I have no idea if it's guaranteed to work, it feels pretty hackish. Given your assumptions that int is 4 bytes, this is guaranteed to work. This is a special case of accessing data as a "char" (and similar) as opposed to accessing it as what it is. If you had a char array and put in a representation of an int into it, do not expect to see the int value when you access that memory through an int*.
Really? Why wouldn't it work? It is not guaranteed to work because a compiler is allowed to assume that data of a certain type is only accessed in certain ways. That is, C and C++ employs type based aliasing rules. See http://en.wikipedia.org/wiki/Pointer_alias and http://en.wikipedia.org/wiki/Type_punning on why violating the rules can lead to badness. |
|
|
|
|
|
|
|