Why is argc an 'int' (rather than an 'unsigned int')?
Why is the command line arguments count variable (traditionally argc
) an int
instead of an unsigned int
? Is there a technical reason for this?
I've always just ignored it when trying rid of all my signed unsigned comparison warnings, but never understood why it is the开发者_Python百科 way that it is.
The fact that the original C language was such that by default any variable or argument was defined as type int, is probably another factor. In other words you could have:
main(argc, char* argv[]); /* see remark below... */
rather than
int main(int argc, char *argv[]);
Edit: effectively, as Aaron reminded us, the very original syntax would have been something like
main(argc, argv) char **argv {... }
Since the "prototypes" were only introduced later. That came roughly after everyone had logged a minimum of at least 10 hours chasing subtle (and not so subtle) type-related bugs
A few reasons:
- because it doesn't matter
- because C did not originally have the
unsigned
keyword or unsigned integer types - because C did not originally check parameter types and did not even have prototypes.
As a result, it was common practice to not even declareint
types, as this was the default. - because
int
was, in a sense, more important back then. Everything was an int. C evolved in part from a language that did not even have types. Every single varable was aword
, which is whatint
originally was used for.
UPDATE: Jason S asked for sources. I think you can dig all of this (except for "it doesn't matter") out of a paper by dmr which is on line: The Development of the C Language. You may need to look up the earlier languages BCPL and B in the usual places.
Because C is old, and it was designed that way from the start. It's too late to change it now.
Here's a history of the C programming language in dmr's own words. It's not stated explicitly (at least not from the quick skim I gave it), but the earliest versions of C didn't support unsigned types. mjv's point about implicit typing to int
is also relevant.
EDIT
The Bell Labs link has been broken for a while: here's an alternate link to the same paper.
Another reason could be that unsigned types can be inconvenient for iteration. For example, this snippet iterating down:
for (size_t i = SIZE - 1; i >= 0; --i)
...
Is, in fact, a bug. When i reaches 0 in the last iteration, it will go on right into 4294967295 (on a 32-bit machine) and the loop won't terminate.
For this reason, I personally find plain ints more convenient for iteration. You don't have to be especially careful when you switch a for
loop from counting up to counting down when using ints.
The Google C++ Style Guide suggests never to use unsigned int
types unless you're working with actual bit patterns. Their rationale applies to C as well. Quick summary line:
... C's type-promotion scheme causes unsigned types to behave differently than one might expect. ... Don't use an unsigned type.
This was probably not in the minds of the original creator's of C, but who knows‽
As a solution to your warning problem, you could do something like this to suppress the warnings:
const unsigned int uargc = (unsigned int) argc;
It was a prescient design decision to make it easier to port C programs to Java in the future since there are no unsigned types in Java.
The declaration for main()
was defined before the unsigned types were added to the language - see DMR's page on 'Primeval C'. It was too late to change when unsigned was added.
I see how it might seem weird: argc
should not be negative! But look at it this way: both int
and unsigned int
cover the range of values you'd accept (if you have 2^31 command line parameters, you have a problem) and int
is shorter to type.
Interview puzzle question: how many keyboards would have been used up typing the unsigned
if C had gone with unsigned int argc
?
By setting it to int, the range is limited to between 1 and INT_MAX inclusive. This will typically mean that no accidental cast or alias will take it out of range from an inadvertent wrap around. It also allows implementations to use the entire negative and 0 range for system specific scenarios.
Ok, I just made that up. The real reason is that it was just an arbitrary decision that one of the original C language developers made, and nobody really thought that hard about it until now. :)
Just a simple question: Do you expect more than 231 (or even more than 215) command line arguments? I doubt that most operating systems could handle that many.
I suppose it is designed to be compatible with C, and in C times people didn't really care that much about signed/unsigned correctness.
精彩评论