printf conversion problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • buzzdee

    printf conversion problem

    hi,

    i just wanted to print out
    some unsigned long int values in hexadecimal,
    printing out one value works, but not byte by byte.
    anybody has a suggestinon what my problem is?

    this is my program:


    #include <stdio.h>
    #include <stdlib.h>
    #include <arpa/inet.h>

    #include <stdio.h>
    int main (void) {
    unsigned long testint = 6070;
    unsigned long bigend = htonl(testint);
    char *le = (char *) &testint;
    char *be = (char *) &bigend;

    printf("HO: %08X\n", testint);
    printf("NO: %08X\n", bigend);

    printf("HO: %02X %02X %02X %02X\n", le[0], le[1], le[2], le[3]);
    printf("NO: %02X %02X %02X %02X\n", be[0], be[1], be[2], be[3]);

    }

    and this is my output:

    $ ./test
    HO: 000017B6
    NO: B6170000
    HO: FFFFFFB6 17 00 00
    NO: 00 00 17 FFFFFFB6

    anybody can tell me why i have that FFFFFFB6 Values in the output wiht
    %02X ?

    buzz
  • Jack Klein

    #2
    Re: printf conversion problem

    On Sun, 26 Sep 2004 16:54:46 +0200, buzzdee
    <reitenba@fh-brandenburg.de> wrote in comp.lang.c:

    C has three character types, signed char, unsigned char, and 'plain'
    char, the type you get when you don't specify signed or unsigned.
    'Plain' char is the same as either signed or unsigned char, but it is
    up to the implementation which it is.

    In your case, 'plain' char is signed. The value 0xb6 in a char on
    your implementation has the value -74. When you pass the value of
    that char to printf(), it is converted to an int with the value -74,
    which is represented in your implementation as 0xffffffb6.
    [color=blue]
    > hi,
    >
    > i just wanted to print out
    > some unsigned long int values in hexadecimal,
    > printing out one value works, but not byte by byte.
    > anybody has a suggestinon what my problem is?
    >
    > this is my program:
    >
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <arpa/inet.h>
    >
    > #include <stdio.h>
    > int main (void) {
    > unsigned long testint = 6070;
    > unsigned long bigend = htonl(testint);
    > char *le = (char *) &testint;
    > char *be = (char *) &bigend;[/color]

    Change the types, and the casts, of 'le' and 'be' to unsigned char,
    instead of just 'plain' char.
    [color=blue]
    >
    > printf("HO: %08X\n", testint);
    > printf("NO: %08X\n", bigend);
    >
    > printf("HO: %02X %02X %02X %02X\n", le[0], le[1], le[2], le[3]);
    > printf("NO: %02X %02X %02X %02X\n", be[0], be[1], be[2], be[3]);
    >
    > }
    >
    > and this is my output:
    >
    > $ ./test
    > HO: 000017B6
    > NO: B6170000
    > HO: FFFFFFB6 17 00 00
    > NO: 00 00 17 FFFFFFB6
    >
    > anybody can tell me why i have that FFFFFFB6 Values in the output wiht
    > %02X ?
    >
    > buzz[/color]

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c++-faq-lite/
    alt.comp.lang.l earn.c-c++

    Comment

    • Flash Gordon

      #3
      Re: printf conversion problem

      On Sun, 26 Sep 2004 16:54:46 +0200
      buzzdee <reitenba@fh-brandenburg.de> wrote:
      [color=blue]
      > hi,
      >
      > i just wanted to print out
      > some unsigned long int values in hexadecimal,
      > printing out one value works, but not byte by byte.
      > anybody has a suggestinon what my problem is?
      >
      > this is my program:
      >
      >
      > #include <stdio.h>
      > #include <stdlib.h>
      > #include <arpa/inet.h>
      >
      > #include <stdio.h>
      > int main (void) {
      > unsigned long testint = 6070;
      > unsigned long bigend = htonl(testint);
      > char *le = (char *) &testint;
      > char *be = (char *) &bigend;[/color]
      Try:
      unsigned char *le = (unsigned char *) &testint;
      unsigned char *be = (unsigned char *) &bigend;[color=blue]
      >
      > printf("HO: %08X\n", testint);
      > printf("NO: %08X\n", bigend);[/color]

      According to the man page (my copy of K&R is in the office) %X expects
      an unsigned in not an unsigned long. You want
      printf("HO: %08lX\n", testint);
      printf("NO: %08lX\n", bigend);
      You are also assuming that unsigned long is 32 bits, which is not
      guaranteed by the standard. This is OK if you want at least 32 bits (I
      think), but if you want exactly 32 bits (which from using the
      non-standard htonl I guess you do) you might want to use a typedef which
      you can set to the appropriate type on each system, including using the
      exact width types that are optional in C99 if you use any C99
      implementations ,<OT> and the POSIX ones if you use POSIX systems.
      Why couldn't C99 have adopted the POSIX fixed width types?</OT>
      [color=blue]
      > printf("HO: %02X %02X %02X %02X\n", le[0], le[1], le[2],
      > le[3]);
      > printf("NO: %02X %02X %02X %02X\n", be[0], be[1],
      > be[2], be[3]);[/color]

      You are assuming that CHAR_BIT==8 and sizeof unsigned int == 4. This
      might be true for the systems you care about, but neither is always
      true.
      [color=blue]
      > }
      >
      > and this is my output:
      >
      > $ ./test
      > HO: 000017B6
      > NO: B6170000
      > HO: FFFFFFB6 17 00 00
      > NO: 00 00 17 FFFFFFB6
      >
      > anybody can tell me why i have that FFFFFFB6 Values in the output wiht
      > %02X ?[/color]

      On your system char is obviously signed and your system uses 2s
      complement, so it gets promoted to an int using signed extension, i.e.
      filling the extra bits with what the sign bit was.
      --
      Flash Gordon
      Sometimes I think shooting would be far too good for some people.
      Although my email address says spam, it is real and I read it.

      Comment

      • Martin Ambuhl

        #4
        Re: printf conversion problem

        buzzdee wrote:
        [color=blue]
        > hi,
        >
        > i just wanted to print out
        > some unsigned long int values in hexadecimal,
        > printing out one value works, but not byte by byte.
        > anybody has a suggestinon what my problem is?
        >
        > this is my program:
        >
        >
        > #include <stdio.h>
        > #include <stdlib.h>
        > #include <arpa/inet.h>
        >
        > #include <stdio.h>
        > int main (void) {
        > unsigned long testint = 6070;
        > unsigned long bigend = htonl(testint);
        > char *le = (char *) &testint;
        > char *be = (char *) &bigend;
        >
        > printf("HO: %08X\n", testint);
        > printf("NO: %08X\n", bigend);
        >
        > printf("HO: %02X %02X %02X %02X\n", le[0], le[1], le[2], le[3]);
        > printf("NO: %02X %02X %02X %02X\n", be[0], be[1], be[2], be[3]);
        >
        > }
        >
        > and this is my output:
        >
        > $ ./test
        > HO: 000017B6
        > NO: B6170000
        > HO: FFFFFFB6 17 00 00
        > NO: 00 00 17 FFFFFFB6
        >
        > anybody can tell me why i have that FFFFFFB6 Values in the output wiht
        > %02X ?[/color]

        Because you have signed chars:


        #include <stdio.h>
        #include <stdlib.h>

        #include <stdio.h>
        int main(void)
        {
        unsigned long testint = 6070;
        unsigned long bigend = 0xb6170000;
        unsigned char *le = (unsigned char *) &testint; /* mha: fixed types
        */
        unsigned char *be = (unsigned char *) &bigend; /* mha: fixed types
        */

        printf("HO: %08lX\n", testint); /* mha: fixed specifier */
        printf("NO: %08lX\n", bigend); /* mha: fixed specifier */
        if (sizeof(unsigne d long) < 4) {
        fprintf(stderr, "Damn!\n");
        exit(EXIT_FAILU RE);
        }
        printf("HO: %02X %02X %02X %02X\n", le[0], le[1], le[2], le[3]);
        printf("NO: %02X %02X %02X %02X\n", be[0], be[1], be[2], be[3]);
        return 0;
        }

        [output]

        HO: 000017B6
        NO: B6170000
        HO: B6 17 00 00
        NO: 00 00 17 B6

        Comment

        Working...