views:

157

answers:

2

Working on a simple C program I'm stuck with an if test:

int line_number = 0;
if ((line_number >= argv[2]) && (line_number <= argv[4]))

gcc says:

cp.c:25: warning: comparison between pointer and integer
cp.c:25: warning: comparison between pointer and integer

What can I do to properly check the range of lines I want to deal with?

+8  A: 

Of course it doesn't work: argv is a pointer to pointer to char.. it's not clear what you want to do but think about that argv[2] is third parameter and argv[4] is fifth one. But they are of char* type (they are strings) so if you want to parse them as integers you should do it using the function atoi:

int value = atoi(argv[2]);

will parse int that was as third parameter and place it into variable, then you can check whatever you want.

Jack
Thanks Jack, you made myd day :)
Samantha
Well, you probably *should* do it using `strtol`. `atoi` is easier to use but harder to handle bad input.
Steve Jessop
A: 

You should not be using function atoi. If fact, you should forget it ever existed. It has no practical uses.

While Jack's answer is correct in stating that the argv strings have to be converted to numbers first, using atoi for that purpose (specifically in the situation when the input comes from the "outside world") is a crime against C programming. There are virtually no situations when atoi can be meaningfully used in a program.

The function that you should be using in this case is strtol

char *end;
long long_value = strtol(argv[2], &end, 10);
if (*end != '\0' || errno == ERANGE)
  /* Conversion error happened */;

The exact error checking condition (like whether to require *end == '\0') will actually depend on your intent.

If you want to obtain an int in the end, you should also check the value for int range (or for your application-specific range)

if (long_value < INT_MIN || long_value > INT_MAX)
  /* Out of bounds error */;

int value = long_value;
/* This is your final value */
AndreyT
While I agree that you should not use atoi *most* of the time, it is practical to use it when you already know the input is valid. For example, you might've already validated the data against a BNF grammar as part of some larger parsing.
Roger Pate
"previous answer"? This is the top-rated answer. There's no "previous". `atoi` does not appear in the question anywhere. Can you edit this answer so it makes sense as a "stand-alone" answer?
S.Lott
Thanks Andrey for your reply, but I don't see why I should never use atoi? is it not a POSIX function?
Samantha
@Roger Pate: Firstly, you'd have to make sure that your grammar is in full synch iwith `atoi` "grammar" (a dubious approach already). But secondly (and more importantly), how are you going to perform the range check using the grammar? I don't see any meaningful way to perform range validation without actually converting the number (moreover, I don't see the point to even search for any other way).
AndreyT
@nour: I consider the issue from C language point of view (not involving POSIX). `atoi` function provides no means for error checking. For example, overflow in the input causes undefined behavior in `atoi`. Which is why `atoi` is useless. In your case the input comes from outside, from the user. This is exactly the case when the error checking is mandatory.
AndreyT
If POSIX offers some additional guarantees for `atoi` - fine. But that would be a different story. The question is tagged C.
AndreyT
@AndreyT: No, fully supporting the input format of atoi is not required, merely any subset of it. Why do you say that's dubious? Do you expect atoi's input format to change sometime soon?
Roger Pate
@Roger Pate: I called it that because I personally dislike the approaches when the functionality of one algorithm has to be synchrohized the the functionality of another, independent algorithm. If introduces an unnecessary invariant and persistent danger of the two coming out of sync. Of course, we have to do something like that from time to time, but I don't see the reason to do it in this case.
AndreyT
I think `atoi` will return `0` if it can't convert the input. But i remember i couldn't quite figure it out without doubts when i checked the Standard last time. Standard says "except for error checking, it's equivalent to strtol(...)", but the 0-on-error-return thing is not listed under the error-checking section for strtol, so i was left wondering.
Johannes Schaub - litb
Notice that your error condition does not account for an empty input string (when `end` will always point to the terminating `'\0'`)
Johannes Schaub - litb
Yeah, I kind of have this habit of doing the empty string check before conversion - it usually turns out that way by itself. Otherwise, I agree that the check is needed.
AndreyT
Using `atoi` is akin to dereferencing a pointer parameter without checking that it's non-NULL, or locking a `pthread_mutex_t*` parameter without checking it has been inited. You are making the caller responsible for providing valid input. That's usually a bad idea when the "caller" is a command-line, because we try to be forgiving of external input, whereas we're very trusting of pointer parameters. But it is at least possible to invent cases where `atoi` is usable, basically when the docs say "give me a sensible integer or get stupid behaviour".
Steve Jessop