C macro to declare unsigned long from "ABCD"

Discussion in 'C Programming' started by Andre, Mar 9, 2012.

  1. Andre

    Andre Guest

    Dear all,

    I would like to handle a table of 4-byte long strings by just declaring
    them as an array of unsigned 32 bit values.
    Of course, this can be done manually, but it would be great if a macro
    XY existed, that, for example, from
    XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344

    Is anybody aware of a macro that does this?

    Best regards,

    Andre
     
    Andre, Mar 9, 2012
    #1
    1. Advertising

  2. Andre

    JohnF Guest

    Andre <> wrote:
    > I would like to handle a table of 4-byte long strings by just declaring
    > them as an array of unsigned 32 bit values.
    > Of course, this can be done manually, but it would be great if a macro
    > XY existed, that, for example, from
    > XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    > Is anybody aware of a macro that does this? Best regards, Andre


    Maybe just try...
    #include <stdio.h>
    #define uint unsigned int
    #define XY(s) (((uint)(*(s+3))) + 256*( ((uint)(*(s+2))) \
    + 256*( ((uint)(*(s+1))) + 256*((uint)(*s)) )))
    int main ( int argc, char *argv[] ) {
    unsigned int xy = XY((argc>1?argv[1]:"ABCD"));
    printf("%08X\n",xy); }
    --
    John Forkosh ( mailto: where j=john and f=forkosh )
     
    JohnF, Mar 9, 2012
    #2
    1. Advertising

  3. Andre <> wrote:
    > I would like to handle a table of 4-byte long strings by just declaring
    > them as an array of unsigned 32 bit values.
    > Of course, this can be done manually, but it would be great if a macro
    > XY existed, that, for example, from
    > XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344


    Not sure what you mean by "declaration" here but perhaps some-
    thing like this is what you're looking for

    #include <stdio.h>
    #include <stdint.h>

    #define XY( x ) ( x[0] << 24 | x[1] << 16 | x[2] << 8 | x[3] )

    int main( void )
    {
    uint32_t x = XY( "ABCD" );
    printf( "0x%08x\n", x );
    return 0;
    }

    Of course, the normal caveats apply, i.e. your relying on a
    certain character encoding, that a char has 8 bits etc. And
    that the macro argument is really something that is a pointer
    to an array-like object with at least four chars.

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Mar 9, 2012
    #3
  4. Andre

    Andre Guest

    On 09.03.2012 11:55, JohnF wrote:
    > Andre<> wrote:
    >> I would like to handle a table of 4-byte long strings by just declaring
    >> them as an array of unsigned 32 bit values.
    >> Of course, this can be done manually, but it would be great if a macro
    >> XY existed, that, for example, from
    >> XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    >> Is anybody aware of a macro that does this? Best regards, Andre

    >
    > Maybe just try...
    > #include<stdio.h>
    > #define uint unsigned int
    > #define XY(s) (((uint)(*(s+3))) + 256*( ((uint)(*(s+2))) \
    > + 256*( ((uint)(*(s+1))) + 256*((uint)(*s)) )))
    > int main ( int argc, char *argv[] ) {
    > unsigned int xy = XY((argc>1?argv[1]:"ABCD"));
    > printf("%08X\n",xy); }


    Cool, works.
    I had expected that it wouldn't because of alignment...
     
    Andre, Mar 9, 2012
    #4
  5. Andre

    Noob Guest

    Andre wrote:

    > I would like to handle a table of 4-byte long strings by just declaring
    > them as an array of unsigned 32 bit values.
    > Of course, this can be done manually, but it would be great if a macro
    > XY existed, that, for example, from
    > XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    >
    > Is anybody aware of a macro that does this?


    First stab, no cigar :-(

    #define XY(s) ( s[0]<<24 | s[1]<<16 | s[2]<<8 | s[3] )
    unsigned arr[] =
    {
    XY("ABCD"),
    XY("EFGH"),
    XY("IJKL"),
    };

    $ gcc mini.c
    mini.c:4:3: error: initializer element is not constant
    mini.c:4:3: error: (near initialization for 'arr[0]')
    mini.c:5:3: error: initializer element is not constant
    mini.c:5:3: error: (near initialization for 'arr[1]')
    mini.c:6:3: error: initializer element is not constant
    mini.c:6:3: error: (near initialization for 'arr[2]')
     
    Noob, Mar 9, 2012
    #5
  6. Andre

    Noob Guest

    Noob wrote:

    > Andre wrote:
    >
    >> I would like to handle a table of 4-byte long strings by just declaring
    >> them as an array of unsigned 32 bit values.
    >> Of course, this can be done manually, but it would be great if a macro
    >> XY existed, that, for example, from
    >> XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    >>
    >> Is anybody aware of a macro that does this?

    >
    > First stab, no cigar :-(
    >
    > #define XY(s) ( s[0]<<24 | s[1]<<16 | s[2]<<8 | s[3] )
    > unsigned arr[] =
    > {
    > XY("ABCD"),
    > XY("EFGH"),
    > XY("IJKL"),
    > };
    >
    > $ gcc mini.c
    > mini.c:4:3: error: initializer element is not constant
    > mini.c:4:3: error: (near initialization for 'arr[0]')
    > mini.c:5:3: error: initializer element is not constant
    > mini.c:5:3: error: (near initialization for 'arr[1]')
    > mini.c:6:3: error: initializer element is not constant
    > mini.c:6:3: error: (near initialization for 'arr[2]')


    There is a work-around if you're willing to break the string up.

    #define YX(A,B,C,D) ( A<<24 | B<<16 | C << 8 | D )
    unsigned arr[] =
    {
    YX('A','B','C','D'),
    YX('E','F','G','H'),
    };

    $ gcc -Wall -Wextra -Os -S mini.c
    $ cat mini.s
    .file "mini.c"
    ..globl _arr
    .data
    .align 4
    _arr:
    .long 1094861636
    .long 1162233672


    NB: 1094861636 = 0x41424344 and 1162233672 = 0x45464748
     
    Noob, Mar 9, 2012
    #6
  7. Andre <> writes:

    > I would like to handle a table of 4-byte long strings by just
    > declaring them as an array of unsigned 32 bit values.


    A word of warning... The result won't be a string even, when you
    construct a character pointer to the int, because there will be no null
    terminator.

    <snip>
    --
    Ben.
     
    Ben Bacarisse, Mar 9, 2012
    #7
  8. Andre

    Eric Sosman Guest

    On 3/9/2012 5:27 AM, Andre wrote:
    > Dear all,
    >
    > I would like to handle a table of 4-byte long strings by just declaring
    > them as an array of unsigned 32 bit values.
    > Of course, this can be done manually, but it would be great if a macro
    > XY existed, that, for example, from
    > XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    >
    > Is anybody aware of a macro that does this?


    Others have offered macros that produce values from the
    characters of strings, but note that the results are not
    integer constant expressions. You could use them this way:

    if (XY(string) == XY("ABCD")) ...

    but not this way:

    switch(XY(string)) {
    case XY("ABCD"): ...
    case XY("WXYZ"): ...
    }

    If this doesn't satisfy your need, perhaps you could describe
    your situation more concretely. Someone's likely to come up with
    another approach if it's needed.

    --
    Eric Sosman
    d
     
    Eric Sosman, Mar 9, 2012
    #8
  9. Andre

    James Kuyper Guest

    On 03/09/2012 07:11 AM, Ben Bacarisse wrote:
    > Noob <root@127.0.0.1> writes:
    > <snip>
    >> There is a work-around if you're willing to break the string up.
    >>
    >> #define YX(A,B,C,D) ( A<<24 | B<<16 | C << 8 | D )
    >> unsigned arr[] =
    >> {
    >> YX('A','B','C','D'),
    >> YX('E','F','G','H'),
    >> };

    >
    > If the OP is prepared to step outside of portable C:
    >
    > unsigned arr[] =
    > {
    > 'ABCD',
    > 'EFGH'
    > };


    He specified in the Subject: header that he's looking for unsigned long,
    not unsigned. UINT_MAX could be as small as 0xFFFF, in which case it
    would be absolutely guaranteed that this array does not contain the
    values he's looking for.

    You should identify precisely what the portability issue is. This code
    must be accepted by any conforming C compiler - that's not what the
    problem is. However, while C does allow character constants to contain
    multiple characters, the value of such constants is an
    implementation-defined int value. Since INT_MAX could be as small as
    0x7FFF, on many implementations it would be impossible to form a
    character constant with the right value. Even on implementations where
    int is 32 bits, the value could be anything from INT_MIN to INT_MAX.
    Without even considering systems which use character encoding
    incompatible with ASCII, plausible values for 'ABCD' other than
    0x41424344 include 0x44434241, 0x4142, 0x4443, 0x41, and 0x44.
    --
    James Kuyper
     
    James Kuyper, Mar 9, 2012
    #9
  10. Andre

    BartC Guest

    "Andre" <> wrote in message
    news:jjclv6$hnq$...
    > Dear all,
    >
    > I would like to handle a table of 4-byte long strings by just declaring
    > them as an array of unsigned 32 bit values.


    Not sure if this is useful, but the following array of 4-char strings is
    also accessed here via an int pointer (ie. an int array). (Substitute an
    unsigned long here.)

    #include <stdio.h>

    char shortstrings[][4]={"ONE","TWO","THRE","FOUR","FIVE"};
    int *ishortstrings=shortstrings;

    int main(void)
    {
    int i;

    for(i=0; i<5; ++i){
    printf("%d:<%04X> <%.4s>\n", i, ishortstrings,
    (char*)&ishortstrings );
    }

    }

    --
    Bartc
     
    BartC, Mar 9, 2012
    #10
  11. JohnF <> writes:
    > Andre <> wrote:
    >> I would like to handle a table of 4-byte long strings by just declaring
    >> them as an array of unsigned 32 bit values.
    >> Of course, this can be done manually, but it would be great if a macro
    >> XY existed, that, for example, from
    >> XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    >> Is anybody aware of a macro that does this? Best regards, Andre

    >
    > Maybe just try...
    > #include <stdio.h>
    > #define uint unsigned int
    > #define XY(s) (((uint)(*(s+3))) + 256*( ((uint)(*(s+2))) \
    > + 256*( ((uint)(*(s+1))) + 256*((uint)(*s)) )))
    > int main ( int argc, char *argv[] ) {
    > unsigned int xy = XY((argc>1?argv[1]:"ABCD"));
    > printf("%08X\n",xy); }


    Why is "uint" a macro? Make it a typedef:

    typedef unsigned int uint;

    Or just use "unsigned int":

    #define XY(s) (((unsigned int)(*(s+3))) + \
    256*(((unsigned int)(*(s+2))) + \
    256*(((unsigned int)(*(s+1))) + \
    256*((unsigned int)(*s)))))

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Mar 9, 2012
    #11
  12. "BartC" <> writes:

    > "Andre" <> wrote in message
    > news:jjclv6$hnq$...
    >> Dear all,
    >>
    >> I would like to handle a table of 4-byte long strings by just
    >> declaring them as an array of unsigned 32 bit values.

    >
    > Not sure if this is useful, but the following array of 4-char strings
    > is also accessed here via an int pointer (ie. an int
    > array). (Substitute an unsigned long here.)
    >
    > #include <stdio.h>
    >
    > char shortstrings[][4]={"ONE","TWO","THRE","FOUR","FIVE"};
    > int *ishortstrings=shortstrings;


    That may well have alignment problems.

    This may work better:

    union {
    char cv[sizeof(unsigned long)];
    unsigned long lv;
    } longs[] = { "ONE", "TWO, "THRE", "FOUR", "FIVE" };

    --
    Ben.
     
    Ben Bacarisse, Mar 9, 2012
    #12
  13. Andre

    Tim Rentsch Guest

    James Kuyper <> writes:

    > On 03/09/2012 07:11 AM, Ben Bacarisse wrote:
    >> Noob <root@127.0.0.1> writes:
    >> <snip>
    >>> There is a work-around if you're willing to break the string up.
    >>>
    >>> #define YX(A,B,C,D) ( A<<24 | B<<16 | C << 8 | D )
    >>> unsigned arr[] =
    >>> {
    >>> YX('A','B','C','D'),
    >>> YX('E','F','G','H'),
    >>> };

    >>
    >> If the OP is prepared to step outside of portable C:
    >>
    >> unsigned arr[] =
    >> {
    >> 'ABCD',
    >> 'EFGH'
    >> };

    >
    > He specified in the Subject: header that he's looking for unsigned long,
    > not unsigned. UINT_MAX could be as small as 0xFFFF, in which case it
    > would be absolutely guaranteed that this array does not contain the
    > values he's looking for.
    >
    > You should identify precisely what the portability issue is. This code
    > must be accepted by any conforming C compiler - [snip]


    That's wrong, in exactly the case you mention. An implementation
    that has 16 bit ints could reject it because the value isn't in
    the range of values representable in type 'int'.
     
    Tim Rentsch, Mar 9, 2012
    #13
  14. Andre

    Tim Rentsch Guest

    Keith Thompson <> writes:

    > JohnF <> writes:
    >> Andre <> wrote:
    >>> I would like to handle a table of 4-byte long strings by just declaring
    >>> them as an array of unsigned 32 bit values.
    >>> Of course, this can be done manually, but it would be great if a macro
    >>> XY existed, that, for example, from
    >>> XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    >>> Is anybody aware of a macro that does this? Best regards, Andre

    >>
    >> Maybe just try...
    >> #include <stdio.h>
    >> #define uint unsigned int
    >> #define XY(s) (((uint)(*(s+3))) + 256*( ((uint)(*(s+2))) \
    >> + 256*( ((uint)(*(s+1))) + 256*((uint)(*s)) )))
    >> int main ( int argc, char *argv[] ) {
    >> unsigned int xy = XY((argc>1?argv[1]:"ABCD"));
    >> printf("%08X\n",xy); }

    >
    > Why is "uint" a macro? Make it a typedef:
    >
    > typedef unsigned int uint;
    >
    > Or just use "unsigned int":
    >
    > #define XY(s) (((unsigned int)(*(s+3))) + \
    > 256*(((unsigned int)(*(s+2))) + \
    > 256*(((unsigned int)(*(s+1))) + \
    > 256*((unsigned int)(*s)))))


    Why use a type name at all?

    #define XY(s) ( ( (0*256UL + 1) * 256 + 2) * 256 + 3)
     
    Tim Rentsch, Mar 9, 2012
    #14
  15. Andre

    Kaz Kylheku Guest

    On 2012-03-09, Andre <> wrote:
    > Dear all,
    >
    > I would like to handle a table of 4-byte long strings by just declaring
    > them as an array of unsigned 32 bit values.
    > Of course, this can be done manually, but it would be great if a macro
    > XY existed, that, for example, from
    > XY("ABCD") would generate a unsigned 32bit declaration like 0x41424344
    >
    > Is anybody aware of a macro that does this?


    I would recommend giving up on XY("ABCD"), and instead do:

    #define FOURCC(A,B,C,D) ((unsigned long) (A) << 24 | \
    (unsigned long) (B) << 16 | \
    (unsigned) (C) << 8 | (D))


    Then call it like this, with character constants:

    FOURCC('A', 'B', 'C', 'D')
     
    Kaz Kylheku, Mar 10, 2012
    #15
  16. Andre

    Andre Guest

    Cool, I like this very much, and it does indeed work for VisualDSP (a
    compiler for a DSP processor).

    However, GNU C does not like it...

    Best regards,

    Andre


    On 09.03.2012 13:11, Ben Bacarisse wrote:
    > Noob<root@127.0.0.1> writes:
    > <snip>
    >> There is a work-around if you're willing to break the string up.
    >>
    >> #define YX(A,B,C,D) ( A<<24 | B<<16 | C<< 8 | D )
    >> unsigned arr[] =
    >> {
    >> YX('A','B','C','D'),
    >> YX('E','F','G','H'),
    >> };

    >
    > If the OP is prepared to step outside of portable C:
    >
    > unsigned arr[] =
    > {
    > 'ABCD',
    > 'EFGH'
    > };
    >
    > <snip>
     
    Andre, Mar 22, 2012
    #16
  17. Andre

    Andre Guest

    I have to correct myself: GNU does accept it!
    Thanks a lot!

    best regards,

    Andre

    On 22.03.2012 17:34, Andre wrote:
    > Cool, I like this very much, and it does indeed work for VisualDSP (a
    > compiler for a DSP processor).
    >
    > However, GNU C does not like it...
    >
    > Best regards,
    >
    > Andre
    >
    >
    > On 09.03.2012 13:11, Ben Bacarisse wrote:
    >> Noob<root@127.0.0.1> writes:
    >> <snip>
    >>> There is a work-around if you're willing to break the string up.
    >>>
    >>> #define YX(A,B,C,D) ( A<<24 | B<<16 | C<< 8 | D )
    >>> unsigned arr[] =
    >>> {
    >>> YX('A','B','C','D'),
    >>> YX('E','F','G','H'),
    >>> };

    >>
    >> If the OP is prepared to step outside of portable C:
    >>
    >> unsigned arr[] =
    >> {
    >> 'ABCD',
    >> 'EFGH'
    >> };
    >>
    >> <snip>

    >
     
    Andre, Mar 23, 2012
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. George Marsaglia

    Assigning unsigned long to unsigned long long

    George Marsaglia, Jul 8, 2003, in forum: C Programming
    Replies:
    1
    Views:
    755
    Eric Sosman
    Jul 8, 2003
  2. Daniel Rudy

    unsigned long long int to long double

    Daniel Rudy, Sep 19, 2005, in forum: C Programming
    Replies:
    5
    Views:
    1,248
    Peter Shaggy Haywood
    Sep 20, 2005
  3. shaanxxx

    int i ='abcd';

    shaanxxx, Aug 25, 2006, in forum: C Programming
    Replies:
    3
    Views:
    461
    shaanxxx
    Aug 27, 2006
  4. pozz
    Replies:
    12
    Views:
    796
    Tim Rentsch
    Mar 20, 2011
  5. John

    id="abcd" in XML

    John, Dec 20, 2006, in forum: Perl Misc
    Replies:
    5
    Views:
    130
    John Bokma
    Dec 21, 2006
Loading...

Share This Page