1) According to my understanding, main function can be defined in any
of the following two ways,
int main(void)
int main(int argc,char *argv[])
How can the same function can have two different signatures ?
"It can't."
Really, that *is* the answer. You pick one of the two and compile
your module that contains your main(). The compiler is required
to look at your main() and, if it is one of those two forms, it
will make it work. How it makes it work is up to the compiler.
One way to "make it work" is to generate, in the actual executable
program you will run, either "2arg_main" or "0arg_main" (note that
both of these names are not something *you*, the programmer, can
enter; but your compiler can use those names behind your back, as
it were). Then, if you call your own main() recursively, or when
it comes time for the startup code to call your main(), the compiler
just has to make sure that it calls the correct one of these two.
(There are other ways to "make it work" that depend on the target
system, and most real compilers use one of those, since those are
usually easier.)
2) My second question is ,
#include<stdio.h>
int main(void)
{
int *p = (int*) 1;
int *q = (int*) 2000;
printf("%d\n",(q-1));
printf("%d\n",(q-p));
}
output:
1996
499
I can understand why the first printf outputs 1996, (because when you
decrement an integer pointer, it points to the prevoius integer which
is four bytes offset from the current location)
But i cannot understand why second printf outputs 499 ?
Can anyone throw light on this one ?
The output of these two printf() calls is undefined -- which means
that *any* output you get is correct (or, equivalently, wrong
).
In order to predict what you will get, on some *particular* system,
we need to know a great deal about the internals of that system.
The first problem is that (int *)1 and (int *)2000 produce
implementation-defined pointer values.
The second problem is that %d prints an "int", but (q-1) generates
a pointer value of type "int *".
If your printf() takes "int *" arguments out of pointer registers
(e.g., A0 through A5), and "int" arguments out of integer registers
(e.g., D0 through D7), the output of your first printf() statement
will be whatever was in a "D" register, even though the pointer
you supplied -- q-1 -- was passed in an "A" register. This will
make the first printf()'s output very difficult to predict.
The last printf() is actually the most predictable, provided we
know what happens with conversion of the integer constants 1 and
2000 to (int *). To find the result of subtracting two pointers of
compatible type, we first assert that they point into the same
array object. (If not, the result is undefined.) Then, we simply
find the number of elements between the two pointers -- which is
the same as the integer that, if added to the second pointer, would
have produced the first one:
distance = first - second;
assert(first + distance == second);
This "distance" number can be negative, so the resulting type of
"ptr2 - ptr1" has type "ptrdiff_t" (not type "int"). There is no
printf() format for ptrdiff_t, but we can convert the difference
to "long" and print it with %ld (in C89) or to "long long" and use
"%lld" (in C99):
/* given some array and some valid indices i and j */
ptrdiff_t distance;
ptr1 = &array
;
ptr2 = &array[j];
distance = ptr2 - ptr1;
printf("%ld\n", (long)distance);
assert(distance == j - i);
3) I want to write a function in C (this can be done easily in C++) ,
that takes variable number of arguments. When i googled for this, i
found stdarg facility.
It requires first argument as char format like "%d %d" etc..
This is not the case. See, for instance, the answer to question
15.4 in the FAQ. (Consider the POSIX-specific "execl" function,
as well.)
But what i want is like,
func(1)
func(1,2)
func(1,2,3)
func(1.2,2.3)
etc..........
How can i do this using C ?
You cannot: as shown, there is no way for func() to discover how
many arguments it actually received, nor their types. The reason
printf() takes "%d", "%f", and so on is that the number of "%"s
(not counting "%%" which produces one "%" character) tell it how
many actual arguments to expect, and the letters -- "d", "f", "s",
and so on -- after the "%" tell it what types to expect.
The example in the FAQ (at 15.4) avoids the need for "type"
information by requiring that every parameter to the function
have one particular type ("const char *" every time). It avoids
the need for a count of arguments by requiring that the list of
arguments be terminated by a special marker.
If all the arguments to func() are integers, and none is ever
negative, you could mark the "stopping point" with a -1:
func(1, -1);
func(1, 2, -1);
func(1, 2, 3, -1);
but your last example suggests that sometimes some or all arguments
may have some other type(s).