
-----------------------------------
DtY
Wed Sep 16, 2009 6:18 pm

Is this proper?
-----------------------------------
#include 
#include 

#define makeChrArray(a) (char *)(&a)

int main(void) {
    int myNum = 12345;
    char *mc;
    
    mc = makeChrArray(myNum);
    printf("%d %d %d %d\n",mc
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

-----------------------------------
DemonWasp
Wed Sep 16, 2009 6:33 pm

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
Thu Sep 17, 2009 2:01 am

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;
}[/code]

-----------------------------------
OneOffDriveByPoster
Fri Sep 18, 2009 8:38 am

Re: Is this proper?
-----------------------------------
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
Fri Sep 18, 2009 11:02 am

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]);
[/code]

Note that I haven't tested the above and I may have my syntax wrong, but I think that should work.

-----------------------------------
DtY
Fri Sep 18, 2009 2:57 pm

Re: Is this proper?
-----------------------------------
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?

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.


Thanks. Is there any way to test for endianess at compile time?

-----------------------------------
DemonWasp
Fri Sep 18, 2009 6:36 pm

RE:Is this proper?
-----------------------------------
My example code won't execute, but this will:


#include 

using namespace std;

typedef union my_int {
    int n;
    char b

On my little-endian x86-64 CPU, that results in:
[code]
3039
39 30 0 0
3A 30 0 0
[/code]

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
Fri Sep 18, 2009 8:37 pm

Re: RE:Is this proper?
-----------------------------------
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.

-----------------------------------
OneOffDriveByPoster
Fri Sep 18, 2009 9:16 pm

Re: Is this proper?
-----------------------------------
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.
