Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > First attempt to use strtoll: What am I doing wrong?

Reply
Thread Tools

First attempt to use strtoll: What am I doing wrong?

 
 
robert maas, see http://tinyurl.com/uh3t
Guest
Posts: n/a
 
      02-12-2007
Here's the source:
#include <stdio.h>
#include <errno.h>
main () {
char* str = "9999999999";
long long int llin; char* endptr; /* Set by strtoll */
int nch;
errno = 0;
llin = strtoll(str, &endptr, 10);
printf("errno=%d\n", errno);
nch = endptr-str;
printf("It processed %d digits.\n", nch);
printf("N=%lld\n", llin);
}

Here's the output.
errno=0
It processed 10 digits.
N=1410065407

I expected that last line to print the correct long long value, all 9's.
 
Reply With Quote
 
 
 
 
Jack Klein
Guest
Posts: n/a
 
      02-12-2007
On Sun, 11 Feb 2007 20:45:23 -0800, http://www.velocityreviews.com/forums/(E-Mail Removed) (robert maas,
see http://tinyurl.com/uh3t) wrote in comp.lang.c:

> Here's the source:
> #include <stdio.h>
> #include <errno.h>
> main () {


Make that:

int main()

....or even better:

int main(void)

The current C standard, the one that includes the type "long long",
has also outlawed implicit int.

> char* str = "9999999999";
> long long int llin; char* endptr; /* Set by strtoll */
> int nch;
> errno = 0;
> llin = strtoll(str, &endptr, 10);
> printf("errno=%d\n", errno);
> nch = endptr-str;
> printf("It processed %d digits.\n", nch);
> printf("N=%lld\n", llin);
> }
>
> Here's the output.
> errno=0
> It processed 10 digits.
> N=1410065407
>
> I expected that last line to print the correct long long value, all 9's.


What does your documentation (C book, compiler on-line help, man
pages, whatever) have to say about strtoll()?

OK, I'll give you a hint: where does your documentation say that the
prototype for strtoll() lives?

Under the current C standard, it is invalid to call a function without
a declaration in scope. Under earlier C standards, it is undefined
behavior to call a function without a declaration in scope if the
function returns anything other than an int.

And finally, what does your documentation say about invoking your
compiler in a way that it will warn you when you call a function
without a prototype in scope?

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
 
Reply With Quote
 
 
 
 
Martin Ambuhl
Guest
Posts: n/a
 
      02-12-2007
robert maas, see http://tinyurl.com/uh3t wrote:
> Here's the source:
> #include <stdio.h>
> #include <errno.h>
> main () {
> char* str = "9999999999";
> long long int llin; char* endptr; /* Set by strtoll */
> int nch;
> errno = 0;
> llin = strtoll(str, &endptr, 10);
> printf("errno=%d\n", errno);
> nch = endptr-str;
> printf("It processed %d digits.\n", nch);
> printf("N=%lld\n", llin);
> }
>
> Here's the output.
> errno=0
> It processed 10 digits.
> N=1410065407
>
> I expected that last line to print the correct long long value, all 9's.


And I would expect you to use decent settings for diagnostics.
There are two lines added below and one changed. Notice the output.

#include <stdio.h>
#include <errno.h>
#include <stdlib.h> /* mha: added for strtoll */

int main(void)
{
char *str = "9999999999";
long long int llin;
char *endptr; /* Set by strtoll */
int nch;
errno = 0;
llin = strtoll(str, &endptr, 10);
printf("errno=%d\n", errno);
nch = endptr - str;
printf("It processed %d digits.\n", nch);
printf("N=%lld\n", llin);
return 0;
}

[output]
errno=0
It processed 10 digits.
N=9999999999

 
Reply With Quote
 
robert maas, see http://tinyurl.com/uh3t
Guest
Posts: n/a
 
      02-12-2007
> From: Jack Klein <(E-Mail Removed)>
> What does your documentation (C book, compiler on-line help, man
> pages, whatever) have to say about strtoll()?
> OK, I'll give you a hint: where does your documentation say that the
> prototype for strtoll() lives?


Well, it's my impression that the header file is supposed to tell
the compiler what the prototype is, so it can compile correct
linkage, and also tell the loader where to find the actual module
to load, so the function will be defined at runtime, so the loader
won't bomb with unresolved symbol. So I assumed if the loader
doesn't complain that it can't find the actual function, then the
correct header file must have been included.

But I looked in the online doc again, and I see it says:
#include <stdlib.h> ; #include <limits.h>
So I put in that first one, didn't bother with limits, and that
fixed the problem. Thanks!!

> And finally, what does your documentation say about invoking your
> compiler in a way that it will warn you when you call a function
> without a prototype in scope?


Well I took the stdlib include back out, and tried
-Wmissing-prototypes, but that complained about the three functions
I'm defining, and didn't complain about strtoll.
Then I tried -Wmissing-declarations, which likewise complained
about my own functions but didn't mention strtoll.
Then I tried -Wimplicit-function-declaration, and it said:
tryll.c: In function `tryParseLliTalk':
tryll.c:52: warning: implicit declaration of function `strtoll'
Aha!! Thanks again.

Hmm, I wonder if -Wmain checks for those other things you
mentionned ... nope. -pedantic ? Nope, just complains repeatedly:
warning: ANSI C does not support `long long'

-Wall gives a whole bunch (new expanded version of program I
haven't yet posted):

tryll.c: In function `printflld':
void printflld(long long int n) {

tryll.c:5: warning: int format, different type arg (arg 2)
if ((n>=0) && (n<=9)) printf("%d", n);
(oops, that should be)
if ((n>=0) && (n<=9)) printf("%lld", n);

tryll.c:8: warning: int format, different type arg (arg 2)
printf("%d", n%10);
(OK, I can cast that safely
printf("%d", (int)(n%10));
(Yeah, I almost made the mistake of omitting parens around whole n%10, phew!)

tryll.c: In function `tryParseLliTalk':
tryll.c:52: warning: implicit declaration of function `strtoll'
(yeah, putting the include back in)

tryll.c: At top level:
tryll.c:66: warning: return-type defaults to `int'
main () {
OK, there we go, what you said earlier:
int main (void) {

tryll.c: In function `main':
tryll.c:77: warning: control reaches end of non-void function
OK, I'll do this:
return(0);

gcc tryll.c -Wall
(No warnings!)

Anyway, here's part of what I was going to post before I saw your
reply but this is now moot:

Update from previous posting:
I saw this note:
<http://gcc.gnu.org/ml/gcc-prs/2002-05/msg00695.html>
wherein there's alleged to be a bug in the printf %lld format
directive, so maybe I'm not doing anything wrong with strtoll, it's
getting the correct value parsed, but then the printf %lld is
showing garbage. So I wrote my own (recursive) decimal-print
function to see what value is *really* in the long long int
variable assigned from strtoll. Well I get the same printout as
sprint does, so the %lld format directive isn't the problem. I'm
really getting a bad result from strtoll. So then I wrote my own
substitute for strtoll, and *now* I'm getting the correct long long
int value, which prints correctly via both the %lld directive and
my own %lld substitute.
 
Reply With Quote
 
Barry
Guest
Posts: n/a
 
      02-12-2007

"robert maas, see http://tinyurl.com/uh3t" <(E-Mail Removed)> wrote in
message news:(E-Mail Removed)...
> > From: Jack Klein <(E-Mail Removed)>
> > What does your documentation (C book, compiler on-line help, man
> > pages, whatever) have to say about strtoll()?
> > OK, I'll give you a hint: where does your documentation say that the
> > prototype for strtoll() lives?

>
> Well, it's my impression that the header file is supposed to tell
> the compiler what the prototype is, so it can compile correct
> linkage, and also tell the loader where to find the actual module
> to load, so the function will be defined at runtime, so the loader
> won't bomb with unresolved symbol. So I assumed if the loader
> doesn't complain that it can't find the actual function, then the
> correct header file must have been included.
>
> But I looked in the online doc again, and I see it says:
> #include <stdlib.h> ; #include <limits.h>
> So I put in that first one, didn't bother with limits, and that
> fixed the problem. Thanks!!
>
> > And finally, what does your documentation say about invoking your
> > compiler in a way that it will warn you when you call a function
> > without a prototype in scope?

>
> Well I took the stdlib include back out, and tried
> -Wmissing-prototypes, but that complained about the three functions
> I'm defining, and didn't complain about strtoll.
> Then I tried -Wmissing-declarations, which likewise complained
> about my own functions but didn't mention strtoll.
> Then I tried -Wimplicit-function-declaration, and it said:
> tryll.c: In function `tryParseLliTalk':
> tryll.c:52: warning: implicit declaration of function `strtoll'
> Aha!! Thanks again.
>
> Hmm, I wonder if -Wmain checks for those other things you
> mentionned ... nope. -pedantic ? Nope, just complains repeatedly:
> warning: ANSI C does not support `long long'
>

<OT>
I believe if you check -pedantic again, it does indeed complain.
Additionally you can stop it from complaining about long long
by telling it which stardard to complain about i.e. std=c99.
</OT>


 
Reply With Quote
 
Mark McIntyre
Guest
Posts: n/a
 
      02-12-2007
On Sun, 11 Feb 2007 23:59:09 -0800, in comp.lang.c , (E-Mail Removed)
(robert maas, see http://tinyurl.com/uh3t) wrote:

>> From: Jack Klein <(E-Mail Removed)>
>> What does your documentation (C book, compiler on-line help, man
>> pages, whatever) have to say about strtoll()?
>> OK, I'll give you a hint: where does your documentation say that the
>> prototype for strtoll() lives?

>
>Well, it's my impression that the header file is supposed to tell
>the compiler what the prototype is,


Typically the header /contains/ the prototype.

>so it can compile correct
>linkage, and also tell the loader where to find the actual module
>to load,


no, thats generally the job of the user (via commandline args,
environment variables etc). The header just tells the compiler what
the function looks like.

>so the function will be defined at runtime, so the loader
>won't bomb with unresolved symbol. So I assumed if the loader
>doesn't complain that it can't find the actual function, then the
>correct header file must have been included.


No, it just means your programme compiled. How your envrionment
handles programme loading isn't defined by the compiler.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
Reply With Quote
 
Roberto Waltman
Guest
Posts: n/a
 
      02-12-2007
robert maas wrote:
>... it's my impression that the header file is supposed to tell
>the compiler what the prototype is, so it can compile correct
>linkage, and also tell the loader where to find the actual module
>to load, so the function will be defined at runtime, so the loader
>won't bomb with unresolved symbol. So I assumed if the loader
>doesn't complain that it can't find the actual function, then the
>correct header file must have been included.


Although it would be possible for a C implementation to work that way,
most do not.
In the general case, including the header only provides the compiler
with information on the function's parameters and return type, so that
it may generate correct code.
The linker/loader receives a list of the libraries that should be
included via a totally separated mechanism, including a small list of
"default" libraries.

If in your case the linker did not complain about missing symbols, it
is only because the functions in question were in one of libraries
used by default.

Roberto Waltman

[ Please reply to the group,
return address is invalid ]
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      02-12-2007
(E-Mail Removed) (robert maas, see http://tinyurl.com/uh3t) writes:
[...]
> Update from previous posting:
> I saw this note:
> <http://gcc.gnu.org/ml/gcc-prs/2002-05/msg00695.html>
> wherein there's alleged to be a bug in the printf %lld format
> directive, so maybe I'm not doing anything wrong with strtoll, it's
> getting the correct value parsed, but then the printf %lld is
> showing garbage. So I wrote my own (recursive) decimal-print
> function to see what value is *really* in the long long int
> variable assigned from strtoll. Well I get the same printout as
> sprint does, so the %lld format directive isn't the problem. I'm
> really getting a bad result from strtoll. So then I wrote my own
> substitute for strtoll, and *now* I'm getting the correct long long
> int value, which prints correctly via both the %lld directive and
> my own %lld substitute.


The strtoll() function is new in C99 (obviously, since long long
didn't exist prior to C99). It's possible that your library and your
headers are out of synch; specifically that your library implements
the strtoll() function, but your <stdlib.h> header doesn't provide a
prototype for it.

Crank up your compiler's warning levels and see if you get a warning
about a missing declaration for strtoll() even if you've include
<stdlib.h>. Write a one-line C source file:
#include <stdlib.h>
and, if your compiler supports it, examine the preprocessor's output
<OT>gcc -E</OT>, and see if there's a prototype for strtol() but not
for strtoll().

If this is the problem, a workaround is to provide your own prototype
for strtoll():

unsigned long long int strtoull(
const char * restrict nptr,
char ** restrict endptr,
int base);

But this might cause problems if your implementation *does* properly
support strtoll().

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
Joe Wright
Guest
Posts: n/a
 
      02-13-2007
robert maas, see http://tinyurl.com/uh3t wrote:
>> From: Jack Klein <(E-Mail Removed)>
>> What does your documentation (C book, compiler on-line help, man
>> pages, whatever) have to say about strtoll()?
>> OK, I'll give you a hint: where does your documentation say that the
>> prototype for strtoll() lives?

>
> Well, it's my impression that the header file is supposed to tell
> the compiler what the prototype is, so it can compile correct
> linkage, and also tell the loader where to find the actual module
> to load, so the function will be defined at runtime, so the loader
> won't bomb with unresolved symbol. So I assumed if the loader
> doesn't complain that it can't find the actual function, then the
> correct header file must have been included.
>
> But I looked in the online doc again, and I see it says:
> #include <stdlib.h> ; #include <limits.h>
> So I put in that first one, didn't bother with limits, and that
> fixed the problem. Thanks!!
>
>> And finally, what does your documentation say about invoking your
>> compiler in a way that it will warn you when you call a function
>> without a prototype in scope?

>
> Well I took the stdlib include back out, and tried
> -Wmissing-prototypes, but that complained about the three functions
> I'm defining, and didn't complain about strtoll.
> Then I tried -Wmissing-declarations, which likewise complained
> about my own functions but didn't mention strtoll.
> Then I tried -Wimplicit-function-declaration, and it said:
> tryll.c: In function `tryParseLliTalk':
> tryll.c:52: warning: implicit declaration of function `strtoll'
> Aha!! Thanks again.
>
> Hmm, I wonder if -Wmain checks for those other things you
> mentionned ... nope. -pedantic ? Nope, just complains repeatedly:
> warning: ANSI C does not support `long long'
>
> -Wall gives a whole bunch (new expanded version of program I
> haven't yet posted):
>
> tryll.c: In function `printflld':
> void printflld(long long int n) {
>
> tryll.c:5: warning: int format, different type arg (arg 2)
> if ((n>=0) && (n<=9)) printf("%d", n);
> (oops, that should be)
> if ((n>=0) && (n<=9)) printf("%lld", n);
>
> tryll.c:8: warning: int format, different type arg (arg 2)
> printf("%d", n%10);
> (OK, I can cast that safely
> printf("%d", (int)(n%10));
> (Yeah, I almost made the mistake of omitting parens around whole n%10, phew!)
>
> tryll.c: In function `tryParseLliTalk':
> tryll.c:52: warning: implicit declaration of function `strtoll'
> (yeah, putting the include back in)
>
> tryll.c: At top level:
> tryll.c:66: warning: return-type defaults to `int'
> main () {
> OK, there we go, what you said earlier:
> int main (void) {
>
> tryll.c: In function `main':
> tryll.c:77: warning: control reaches end of non-void function
> OK, I'll do this:
> return(0);
>
> gcc tryll.c -Wall
> (No warnings!)
>
> Anyway, here's part of what I was going to post before I saw your
> reply but this is now moot:
>
> Update from previous posting:
> I saw this note:
> <http://gcc.gnu.org/ml/gcc-prs/2002-05/msg00695.html>
> wherein there's alleged to be a bug in the printf %lld format
> directive, so maybe I'm not doing anything wrong with strtoll, it's
> getting the correct value parsed, but then the printf %lld is
> showing garbage. So I wrote my own (recursive) decimal-print
> function to see what value is *really* in the long long int
> variable assigned from strtoll. Well I get the same printout as
> sprint does, so the %lld format directive isn't the problem. I'm
> really getting a bad result from strtoll. So then I wrote my own
> substitute for strtoll, and *now* I'm getting the correct long long
> int value, which prints correctly via both the %lld directive and
> my own %lld substitute.


Have a look..

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

int main(void) {
char *str = "9999999999";
long long int llin;
char *endptr; /* Set by strtoll */
int nch;
errno = 0;
llin = strtoll(str, &endptr, 10);
printf("errno=%d\n", errno);
nch = endptr - str;
printf("It processed %d digits.\n", nch);
printf("N=%lld\n", llin);
return 0;
}

...which gives me..

errno=0
It processed 10 digits.
N=9999999999

There's not much difference between yours and mine. What is it?

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
 
Reply With Quote
 
robert maas, see http://tinyurl.com/uh3t
Guest
Posts: n/a
 
      02-14-2007
> From: Joe Wright <(E-Mail Removed)>
> Have a look..

(snipped, refer to <(E-Mail Removed)>)
> There's not much difference between yours and mine. What is it?


My *current* version (last edited Feb 11 23:55 PST) looks like this:

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

void printflld(long long int n) {
if ((n>=0) && (n<=9)) printf("%lld", n);
else if (n>9) {
printflld(n/10);
printf("%d", (int)(n%10));
} else {
long long int nneg;
printf("-");
nneg = -n;
if (nneg>0) { /* If n was negative but not most-negative possible. */
printflld(nneg);
} else printf("9223372036854775808"); /* N = most negative long long int */
}
}

/* Requires snum to immediately start with minus sign or first digit.
Doesn't handle leading whitespace nor plus sign. Treats empty string
as zero. Doesn't handle any base except decimal. Doesn't report end
of digits parsed via second parameter. Otherwise should behave as strtoll
was advertised. It *does* set errno in case of overflow! */
long long int mystrtoll(char* snum) {
int sign = 1;
long long int val = 0;
char* ptr = snum;
if (*ptr == '-') {
sign = -1;
ptr++;
}
while (1) {
char ch = *ptr;
if (('0' <= ch) && (ch <= '9')) {
int digval = (ch-'0')*sign;
val = val*10 + digval;
if (digval != val%10) {
errno = ERANGE;
return(-1);
}
ptr++;
} else break;
}
return(val);
}

void tryParseLliTalk(char* str) {
long long int llin; char* endptr; /* Set by strtoll */
int nch;
printf("\n** String is [%s]\n", str);
errno = 0;
llin = strtoll(str, &endptr, 10);
printf("errno=%d\n", errno);
nch = endptr-str;
printf("It processed %d digits.\n", nch);
printf("N = %lld = ", llin);
printflld(llin); printf("\n");
errno = 0;
llin = mystrtoll(str);
printf("errno=%d\n", errno);
printf("N = %lld = ", llin);
printflld(llin); printf("\n");
printf("String is still [%s]\n", str);
}

int main (void) {
tryParseLliTalk("999999999");
tryParseLliTalk("-999999999");
tryParseLliTalk("9999999999");
tryParseLliTalk("-9999999999");
tryParseLliTalk("2147483647");
tryParseLliTalk("2147483648");
tryParseLliTalk("-2147483648");
tryParseLliTalk("9223372036854775807");
tryParseLliTalk("9223372036854775808");
tryParseLliTalk("-9223372036854775808");
return(0);
}

Presumably you're trying to offer corrections to the very first
version I posted. So I went back to my backup copy of that, and
used Compare Windows (feature of McSink), and found these
differences:

Your version has:
#include <stdlib.h>
but mine already got that a few days ago due to somebody else
giving me the clue before you.

Yours has return type int and args void on main, which mine also
got a day or two ago due to somebody else giving me a clue to try
-Wall.

Yours is indented 7 spaces instead of only 2 spaces for the body of
main, so I'll have to reformat yours before I can compare the rest
with mine. (Why do you deliberately make things hard for newbies?)

You've moved the * in the declaration for str, which I already know
is totally irrelevant, so why waste my time?

You've also split the two items set by strtoll, making that comment
a half truth which is a lie. I'd rather violate one-stmt-per-line
police so that I can have a single comment that refers to two
declarations on the same line, than what you did of splitting to
make a half-truth lie, or duplicating the comment onto both lines.

You've inserted spaces around the subtraction operator between two
pointers, as if that was a ****ing important thing to do to make or
break a program. Why can't you stick to what's important?

You included "return 0;", which I already did in response to -Wall
in clue from the person a few days ago already. But what's the
matter with you, you're a perl programmer at heart, love to omit
the parens around arguments to functions, which works *only* when
there's exactly one argument? I prefer always use parens so the
same syntax works uniformly regardless of number of arguments.

So anyway, the only *important* thing you changed was including the
header for stdlib, so that the long long type of return value from
strtoll would be declared and cause correct linkage to be compiled.
(GNU C compiler is too dumb to keep the presumed type around at
linkage time and check against actual type of library functions, so
that a diagnostic could be reported at that time, such as "Error:
Linkage for return value from strtoll assumed type int, but library
function uses long long int instead, making the linkage
incorrect.")
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Troubles with first attempt to use the chart package. Tad J McClellan Perl Misc 1 10-22-2008 09:07 PM
Can't locate object method "first" via package "attempt" (perhaps you forgot to load "attempt"?) at .... GMI Perl Misc 3 06-19-2005 10:44 PM
Problem with first attempt at Swing form Wes Harrison Java 2 01-12-2005 10:02 AM
SQL Question Again - (hit enter and sent first attempt) =?Utf-8?B?U29mdFNwb3Q=?= MCSD 2 09-18-2004 04:14 PM
a first attempt Andrea Fino HTML 0 04-24-2004 04:18 PM



Advertisments