odd behavior from atol

Discussion in 'C++' started by Jon Cosby, Jan 31, 2007.

  1. Jon Cosby

    Jon Cosby Guest

    I'm getting odd output from atol in a for loop. Entering a ten-digit
    string I get different results for char and atol(char). If I drop iSum
    the output seems to be okay. This happens using the g++ compiler. Using
    vc++, I don't get this behavior. Anyone have an explanation for this?

    ////////////////////////////////////
    void test(string sInput)
    {
    int iSum;
    char cCurr;

    sum = 0;

    for (int i = 0; i < sInput.length(); i++)
    {
    cCurr = sInput.at(i);
    cout << cCurr << " : " << atol(& cCurr) << endl;
    iSum += (i + 1) * atol(& cCurr);
    }
    }

    int main()
    {
    string sInput;

    cout << "Enter test string: ";
    cin >> sInput;

    test(sInput);

    return 0;
    }

    ////////////////////////////////////

    jon@linux:~/projects/test> ./test
    Enter test string: 0201530821
    0 : 0
    2 : 2
    0 : 0
    1 : 1
    5 : 5
    3 : 3
    0 : 3 //!!
    8 : 8
    2 : 2
    1 : 1
     
    Jon Cosby, Jan 31, 2007
    #1
    1. Advertising

  2. Jon Cosby

    touche Guest

    Jon Cosby wrote:
    > I'm getting odd output from atol in a for loop. Entering a ten-digit
    > string I get different results for char and atol(char). If I drop iSum
    > the output seems to be okay. This happens using the g++ compiler. Using
    > vc++, I don't get this behavior. Anyone have an explanation for this?
    >
    > ////////////////////////////////////
    > void test(string sInput)
    > {
    > int iSum;
    > char cCurr;
    >
    > sum = 0; // That's iSum!!
    >
     
    touche, Jan 31, 2007
    #2
    1. Advertising

  3. Jon Cosby wrote:
    > I'm getting odd output from atol in a for loop. Entering a ten-digit
    > string I get different results for char and atol(char). If I drop iSum
    > the output seems to be okay. This happens using the g++ compiler.
    > Using vc++, I don't get this behavior. Anyone have an explanation for
    > this?


    Undefined behaviour. Look it up. You're lucky your program didn't
    format your hard drive and didn't send nasty e-mails to your friends
    on your behalf.

    >
    > ////////////////////////////////////
    > void test(string sInput)
    > {
    > int iSum;
    > char cCurr;
    >
    > sum = 0;
    >
    > for (int i = 0; i < sInput.length(); i++)
    > {
    > cCurr = sInput.at(i);
    > cout << cCurr << " : " << atol(& cCurr) << endl;


    'atol' expects an {_array_ of char} that terminates with a null char,
    '\0', and you're supplying it with the address of a single char. Your
    code has undefined behaviour, so anything is possible.

    You can correct it by declaring 'cCurr' an array, initialising it to
    all zeros and the overriding only the first one with the return value
    of 'at'.

    > iSum += (i + 1) * atol(& cCurr);
    > }
    > }
    >
    > int main()
    > {
    > string sInput;
    >
    > cout << "Enter test string: ";
    > cin >> sInput;
    >
    > test(sInput);
    >
    > return 0;
    > }
    >
    > ////////////////////////////////////
    >
    > jon@linux:~/projects/test> ./test
    > Enter test string: 0201530821
    > 0 : 0
    > 2 : 2
    > 0 : 0
    > 1 : 1
    > 5 : 5
    > 3 : 3
    > 0 : 3 //!!
    > 8 : 8
    > 2 : 2
    > 1 : 1


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jan 31, 2007
    #3
  4. Jon Cosby

    Pete Becker Guest

    Jon Cosby wrote:
    > I'm getting odd output from atol in a for loop. Entering a ten-digit
    > string I get different results for char and atol(char). If I drop iSum
    > the output seems to be okay. This happens using the g++ compiler. Using
    > vc++, I don't get this behavior. Anyone have an explanation for this?
    >
    > ////////////////////////////////////
    > void test(string sInput)
    > {
    > int iSum;
    > char cCurr;
    >
    > sum = 0;
    >
    > for (int i = 0; i < sInput.length(); i++)
    > {
    > cCurr = sInput.at(i);


    Belt and suspeners here, eh? Since the loop goes from 0 to
    sInput.length(), you won't get an index out of bounds. But never mind...

    > cout << cCurr << " : " << atol(& cCurr) << endl;


    atol expects a null-terminated character array. This code passes the
    address of a char variable, so the function looks at that char and at
    whatever comes after it in memory. Try this instead:

    char cCurr[2] = {};

    Now stuff your character into cCurr[0].

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Jan 31, 2007
    #4
  5. Jon Cosby

    Rolf Magnus Guest

    Jon Cosby wrote:

    > I'm getting odd output from atol in a for loop. Entering a ten-digit
    > string I get different results for char and atol(char). If I drop iSum
    > the output seems to be okay. This happens using the g++ compiler. Using
    > vc++, I don't get this behavior. Anyone have an explanation for this?


    Your code invokes undefined behavior.

    > ////////////////////////////////////
    > void test(string sInput)
    > {
    > int iSum;
    > char cCurr;
    >
    > sum = 0;
    >
    > for (int i = 0; i < sInput.length(); i++)
    > {
    > cCurr = sInput.at(i);
    > cout << cCurr << " : " << atol(& cCurr) << endl;


    atol expects a pointer to the first element of a zero terminated array of
    char ("C style string"), and you only give it the address of a single char.
    atol will try to read on in the memory beyond the variable until it finds
    something it can interpret as a '\0' character.

    > iSum += (i + 1) * atol(& cCurr);
    > }
    > }
    >
    > int main()
    > {
    > string sInput;
    >
    > cout << "Enter test string: ";
    > cin >> sInput;
    >
    > test(sInput);
    >
    > return 0;
    > }
    >
    > ////////////////////////////////////
    >
    > jon@linux:~/projects/test> ./test
    > Enter test string: 0201530821
    > 0 : 0
    > 2 : 2
    > 0 : 0
    > 1 : 1
    > 5 : 5
    > 3 : 3
    > 0 : 3 //!!
    > 8 : 8
    > 2 : 2
    > 1 : 1
     
    Rolf Magnus, Jan 31, 2007
    #5
  6. On Wed, 31 Jan 2007 13:21:30 -0500, "Victor Bazarov" <>
    wrote:

    >'atol' expects an {_array_ of char} that terminates with a null char,
    >'\0', and you're supplying it with the address of a single char. Your
    >code has undefined behaviour, so anything is possible.


    Well, not exactly. atol expects an array of char that terminates with a
    character that is for which isspace() returns nonzero, or that violates the
    sequence ('+'|'-'|'')('0x'|'0X'|'')(['0'-'9']|['a'-'z']|['A'-'Z'])+

    That's probably why the OP's program didn't immediately crash and burn. The
    chances that a pattern-violating character is in the immediate vicinity of the
    buffer is quite high, and reading from that memory doesn't corrupt any other
    data structures.

    -dr
     
    Dave Rahardja, Jan 31, 2007
    #6
    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. Gizmo
    Replies:
    5
    Views:
    434
    llewelly
    Sep 8, 2003
  2. Sharon
    Replies:
    4
    Views:
    1,022
    CBFalconer
    Nov 17, 2003
  3. Mike Moum

    string.atoi and string.atol broken?

    Mike Moum, Jan 25, 2005, in forum: Python
    Replies:
    19
    Views:
    683
    Peter Otten
    Jan 27, 2005
  4. Olaf
    Replies:
    0
    Views:
    640
  5. Michael Speer

    Odd behavior with odd code

    Michael Speer, Feb 16, 2007, in forum: C Programming
    Replies:
    33
    Views:
    1,135
    Richard Heathfield
    Feb 18, 2007
Loading...

Share This Page