views:

142

answers:

4

Hello,

The C standard (5.1.2.2.1 Program startup) says:

The function called at program startup is named main. [...]
It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }

or with two parameters [...] :
int main(int argc, char *argv[]) { /* ... */ }

And later says:

The value of argc shall be nonnegative.

  • Why shouldn't argc be defined as an unsigned int, argc supposedly meaning 'argument count'?
  • Should argc be used as an index for argv?

So I started wondering if the C standard says something about the type of array's index. Is it signed?

6.5.2.1 Array subscripting:

One of the expressions shall have type ‘‘pointer to object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.

It doesn't say anything about its signedness (or I didn't find it). It is pretty common to see codes using negatives array indexes (array[-1]) but isn't it undefined behavior?

  • Should array's indexes be unsigned?
+6  A: 

The reason for the int in main() is historical - it's always been that way, since long before the language was standardised. The requirement of an array index is that it is within the bounds of the array (or in some circumstances, one past the end) - anything else is undefined, so the signedness is immaterial.

anon
+3  A: 

1) About main() argc type: IMHO the standard continues a very old tradition (more than 30 years!), and now... it's simply too late to change things (NOTE: on most systems neither the compiler, nor the linker, nor the CPU will complain if "argc" is defined "unsigned", but you are out of the standard!)

2) On the majority of implementations argv[argc] is legal and evaluates to NULL. Indeed, an alternate way to find the end of the argument list is to iterate on argv from 0 terminating when argv[i] is NULL.

3) Array/pointer arithmetic with negative numbers is legal as far as the address range from (p-n) to p belongs to the same memory object. I.E. you can have

char array[100];
char *p;

p = &array[50];
p += -30; /* Now p points to array[20]. */

This usage of pointer arithmetic is legal because the resulting pointer still stays inside the original memory object ("array"). On most system the pointer arithmetic can be used to navigate in memory in violation of this rule, but this is NOT portable since it's completely system-dependent.

Giuseppe Guerrini
Having argv[argc] NULL is mandated by the standard.
AProgrammer
A: 
tommieb75
1) I asked why `argc` is not unsigned in the standard, not if I could use negative indexes.2) My second question was the relation between the signedness of `argc` and the signedness of an array's index (aka operator []'s parameter).4) I know, but it's not written in the standard.
Bertrand Marron
Can I ask who downvoted this and why?
tommieb75
+2  A: 

In general in C, the "principle of least surprise" implies that it is preferable to make a variable signed unless there is a good reason for it to be unsigned. This is because the type-promotion rules can lead to unexpected results when you mix signed and unsigned values: for example, if argc was unsigned then this simple comparison would lead to surprising results:

if (argc > -1)

(The -1 is promoted to unsigned int, so its value is converted to UINT_MAX, which is almost certainly greater than argc).

caf
That is an interesting way of explaining it.
Bertrand Marron