Thread: strtol() question

  1. #1
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72

    strtol() question

    hello

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    
    int main(void)
    {
         char *str = "ffffffff";
         int c;
    
         c = strtol(str, 0, 16);
    
         if (errno != 0)
             printf("Strtol overflowed!!!\n");
    
         printf("&#37;d\n", c);
    
         return 0;
    }
    How do I make strtol() read ffffffff as -1 and not UNSIGNED_LONGMAX??

    I'm basically making a conversion program that converts between
    different bases, e.g decimal to hex, hex to decimal, decimal to binary, etc.

    The user can enter ---> cvt -h ffffffff -d and it prints -1
    If the user enters --> cvt -uh ffffffff -d (u stands for unsigned) it prints whatever
    UNSIGNED LONG MAX is.

    The above overflows because it's reading ffffffff as UNSIGNED_LONGMAX.

    Similarly with:
    Code:
             char *srt = "11111111";
       
             c = strtol(str, 0, 2);
    strtol reads 11111111 as 255. Is there a way to make it read 11111111 as -1?
    I know there are various ways without using strtol. Im just wondering if strtol
    has some built in mechanism for reading 11111111 or ffffffff as negative instead
    of positive.

    thanks
    Last edited by movl0x1; 05-15-2007 at 10:38 AM.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Sounds like your strtol() function is broken. Even if it did overflow, it should be returning LONG_MAX, not UNSIGNED_LONGMAX.

    EDIT: On second thought, strtol() isn't broken (although it should be returning LONG_MAX not UNSIGNED_LONGMAX). You're trying to use it in a way it can't be used. It isn't meant to convert bit patterns into integers, it is a number converter. Just because FFFFFFFF happens to represent -1 doesn't mean strtol() will do that. Instead, it sees that FFFFFFFF is larger than 2^31-1, the maximum range of a signed integer, and returns an overflow. This is as it should be.

    Anyway, what makes you think that FFFFFFFF is equal to -1? That's an assumption of 2's complement, an assumption you shouldn't make.
    Last edited by brewbuck; 05-15-2007 at 10:42 AM.

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    If you want to use an unsigned conversion, use strtoul() instead.
    If you understand what you're doing, you're not learning anything.

  4. #4
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    No, strtol is returning LONG_MAX, but interpreting ffffffff as UNSIGNED LONG MAX
    causing it to overflow.

    thanks

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by movl0x1 View Post
    No, strtol is returning LONG_MAX, but interpreting ffffffff as UNSIGNED LONG MAX
    causing it to overflow.

    thanks
    It's not interpreting it as anything other than the number it is, which is 2^32-1. This is larger than the largest signed integer value, so you get an overflow.

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by movl0x1 View Post
    Im just wondering if strtol
    has some built in mechanism for reading 11111111 or ffffffff as negative instead
    of positive.
    A minus sign?
    Code:
         char *str = "-7fffffff";
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    If what you want to do is convert 2's complement values to decimal, strtol() will not do that. Just to be crystal clear. The only way strtol() will return a negative value is if the number has a minus sign in front of it.

  8. #8
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    thanks guys


    If I put a minus in front of 11111111 (-11111111) strtol spits out -255 though, not -1.

    But if the user enters 11111111 and thinks of it as unsigned, he wants the
    program (when converting to decimal) to spit out 255, and if he enters
    11111111 and thinks of it as signed, he wants the program to spit out -1
    when converting to decimal.

    What I'm saying is that 11111111 is converted to 255 with strtol() when it
    reads that character string and converts it to base 2.

    I was wondering if strtol() can convert it to -1 instead.
    Probably not. Guess I'm gonna have to create some type of wrapper.


  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by movl0x1 View Post
    If I put a minus in front of 11111111 (-11111111) strtol spits out -255 though, not -1.
    Sure, that's what it is.

    Quote Originally Posted by movl0x1
    But if the user enters 11111111 and thinks of it as unsigned, he wants the
    program (when converting to decimal) to spit out 255, and if he enters
    11111111 and thinks of it as signed, he wants the program to spit out -1
    when converting to decimal.

    What I'm saying is that 11111111 is converted to 255 with strtol() when it
    reads that character string and converts it to base 2.

    I was wondering if strtol() can convert it to -1 instead.
    Probably not. Guess I'm gonna have to create some type of wrapper.
    I'd guess so. It sounds like you first want to create an integral image given the text representation in a certain base, and then display (interpret) it according to a specified signedness.

    For that I'd say use unsigned conversion to an integral type first, and then a cast for the interpretation. And remember that implementations vary, so this will not be portable as I have described.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  10. #10
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    Oh yeah. Right, thanks. I forgot that 255 in an int (well, on my machine) would be

    00000000 00000000 00000000 11111111. I think that's how strtol would return it in
    the int it assigns it to.

    So read that string "11111111" in with strtoul(), and it put's it in the unsigned int as

    00000000 00000000 00000000 11111111 (255 unsigned)

    typecast it to

    11111111 11111111 11111111 11111111 (-1 unsigned)


    I hope I got it! Thanks to all for your help.


    I did a little example and it did what I wanted

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
               char *str = "ffffffff";
               unsigned = c;
               
               /* user wants 0xffffffff to be interpreted as signed (-1) */
               
               /* get string and convert it to all 1 bits inside unsigned int c */
               c = strtoul(str, 0, 16);
    
               /* use printf  (I believe printf calls itoa() ) to build ascii string out of the int */
               /* printf() interprets c (all 1 bits) as unsigned, therefore printing -1.
               printf("&#37;d\n", c);
    
               return 0;
    }
    Last edited by movl0x1; 05-16-2007 at 04:25 AM.

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    note that the solution is not portable - entered value should be the same size as int, if int is 64bit - your trick will not work...

    Why user does not want to enter -1? It is really shorter.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    this is gonna be a program that converts numbers.

    If you enter ---> cvt -h ffffffff -d

    cvt = (convert - name of my prog) -h string is interpreted as signed hexadecimal
    -d string is converted from ffffffff to its decimal representation.

    Now, if you enter ----> cvt -uh ffffffff -d (-uh meaning unsigned hex)

    It spits out the whatever ULONG_MAX is as a decimal number.

    If I enter ---> cvt -b 11111111 -d it spits out -1

    cvt -d 10 -h spits out ---> 0a

    10 (decimal string) converted to hex is 0a

    It's for GNU/Linux
    Just a little conversion prog I can use to convert numbers back an forth from hex to binary, binary to hex, etc.
    Last edited by movl0x1; 05-16-2007 at 08:55 AM.

  13. #13
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    11111111 in binary is not a LONG_MAX...

    And LONG_MAX is different on different compilers...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  14. #14
    Linux is where it's at movl0x1's Avatar
    Join Date
    May 2007
    Posts
    72
    If I have a 32-bit register or variable this is LONG and ULONG_MAX

    11111111 11111111 11111111 11111111

    ULONG_MAX under my GNU/LINUX 32 bit. Yes, I know it's different on
    different architectures.

    thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Alice....
    By Lurker in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 06-20-2005, 02:51 PM
  2. Debugging question
    By o_0 in forum C Programming
    Replies: 9
    Last Post: 10-10-2004, 05:51 PM
  3. Question about pointers #2
    By maxhavoc in forum C++ Programming
    Replies: 28
    Last Post: 06-21-2004, 12:52 PM
  4. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM
  5. Question, question!
    By oskilian in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 12-24-2001, 01:47 AM