Any differnece between functions

T

Tagore

Recently I was having a chat with my friend about standard way of
writing main function in C.
We were at loggerheads about whether there are any differences between
following two methods..
int main(void)
{ }
int main()
{ }

I think both are same....
Are they?
 
L

Lew Pitcher

Recently I was having a chat with my friend about standard way of
writing main function in C.
We were at loggerheads about whether there are any differences between
following two methods..
int main(void)
{ }
int main()
{ }

I think both are same....
Are they?
No

With
int main(void) {}
main is a function that takes no arguments, and returns an int

With
int main() {}
main is a function that takes an unknown set of arguments, and returns an
int

There is a subtle difference between the two.

--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
T

Tagore

No

With
  int main(void) {}
main is a function that takes no arguments, and returns an int

With
  int main() {}
main is a function that takes an unknown set of arguments, and returns an
int

There is a subtle difference between the two.
Is that means I can define a function as
void A()
{ }

and call it as
A(23,'A');

and still compiler will not show an error but it would not use
arguments passed for obvious reasons.
 
K

Keith Thompson

Not quite. This *declares* main as a function that takes an unknown
number of arguments, but it *defines* it as a function that has no
parameters.
Is that means I can define a function as
void A()
{ }

and call it as
A(23,'A');

and still compiler will not show an error but it would not use
arguments passed for obvious reasons.

The declaration "void A()" means you can call A with any number of
arguments that you like. The definition "void A(){}" means that A has
no parameters. If you call it with one or more arguments, the
compiler isn't obligated to diagnose your error, but the behavior is
undefined. Quietly ignoring the extra arguments is one possible
behavior; crashing is another.
 
S

Stephen Sprunk

Tagore said:
Recently I was having a chat with my friend about standard way of
writing main function in C.
We were at loggerheads about whether there are any differences between
following two methods..
int main(void)
{ }
int main()
{ }

I think both are same....
Are they?

Since those are both definitions for main(), they are identical (i.e.
zero arguments). However, if they were declarations, the latter one
would specify an unknown number of arguments, while the former would
specify zero arguments.

S
 
K

Keith Thompson

Stephen Sprunk said:
Since those are both definitions for main(), they are identical
(i.e. zero arguments). However, if they were declarations, the latter
one would specify an unknown number of arguments, while the former
would specify zero arguments.

A function definition is also a function declaration.

This:

int main(void){}

void foo(void){main(42);}

violates a constraint. This:

int main(){}

void foo(void){main(42);}

does not (though it invokes UB if the call to main is ever executed).

And because they're not equivalent, I've argued that the "int main()"
form is not explicitly permitted by the standard (though an
implementation is free accept it).
 
K

Kaz Kylheku

Since you've included the compound-statement braces, it's clear you're
talking about a function definition.

However, 6.7.5.3{14} contradicts your statement:

"An empty list in a function declarator that is part of a definition
of that function specifies that the function has no parameters."

That's right. int main() {} merely fails to introduce a prototype for the
function into the space of file scope type declarations. This is only
significant if main is followed by functions that make calls to it,
or calls itself. main(3) is not a diagnosable constraint violation given
only int main() { }.
 
K

Kaz Kylheku

Not quite. The compound-statement braces indicate that a function
definition is intended, not merely a function declaration.

Too autistic. The statement ``this declares main'' is not a logical
contradiction of ``this declares main, and this also defines main''.
Not quite. There may be implementation limits on the number of
arguments you can supply.

But in comp.lang.c, it's assumed that exceeding this is something you don't
like. I.e. the number of arguments you like, in this newsgroup, is less
than or equal to the minimum implementation limit. If the number of
arguments is greater than this, you do not like that.
Also, that declaration is subject to
other declarations -- so we have the following counterexample:

Sorry, you can't add more information to the problem and call it a
counterexample. Of course, additional (compatible) declarations could extend
the type knowledge base with an increasingly detailed composite type of void
A(). You cannot add your statements to somenoe's assertion and then claim it
to be false. If someone says P, you cannot extend it to P ^ ~Q and claim that
it contradicts P ^ Q. If someone says that C follows from assumptions P1 and
P2, you cannot add your own P3, and call the argument invalid.

But the declaration void A(), by itself, definitely does not mean you can call
A with any number of arguments you like. That declaration means you don't know
how the hell you should call A, unless you look up the definition. And even
then, what seem like the obvious ways to call A may flop due to some promotion
rules. E.g.

// definition is: void A(float)

A(3.0); // oops, no double -> float coersion, undefined

Even the declaration void A(some_type_t, ...) doesn't mean you can
pass any number of arguments you like. You can probably pass different
numbers of arguments, but only values and combinations that A likes.
Observing A's particular ritual for variable arguments is essential.
------------------------------------------------------
#include <stdio.h>

void A();

void A(int n)
{
printf("%d\n", n);
}

int main(void)
{
A(23); // OK!
// A(23, 'A'); NOT OK!
return 0;
}

Adding your own declaration/definition or other assumptions and calling someone
wrong: NOT (logically) OK.
 
K

Keith Thompson

Richard Heathfield said:
Keith Thompson said:


I think it's fair to assume that he meant "if they were *only*
declarations" - i.e. declarations that are not also definitions.

I'm sure that's what he meant. Nevertheless, the definitions are not
identical, because the declarations that they contain are not
identical.

Given a definition
int main(void){}
a later call to
main(42)
is a constraint violation.

Given a definition
int main(){}
a later call to
main(42)
is not a constraint violation, though it invokes undefined behavior.
(Note that a "later call" could be within the definition of main
itself.)
 
S

s0suk3

Given a definition
    int main(){}
a later call to
    main(42)
is not a constraint violation,

Why? The function was defined (not just declared), right?

Sebastian
 
H

Harald van Dijk

Keith Thompson said:

Even if the function containing main(42) is never called?

Yes, even then. I think you're partly confusing constraint violations
with undefined behaviour here. Undefined behaviour at runtime, for a part
of the code that is never executed, is not a problem. If it were,
if (p != NULL) *p = 1;
would be invalid, because *p = 1; has undefined behaviour when p is a
null pointer. Constraint violations are more like syntax errors, and they
typically get diagnosed before the compiler even has the chance to see
whether the code will ever be executed.
 
T

Tim Rentsch

Keith Thompson said:
Right, but the declaration, which is visible at the point of the call,
doesn't specify the number of parameters.

Micronit:

Technically, the function body is part of the declaration,
which does specify the number of parameters. However,
the /type/ resulting from this definition/declaration
does /not/ specify the number (or types) of parameters,
which is what makes this definition/declaration fail
to be a prototype.
 
T

Tim Rentsch

Richard Heathfield said:
Keith Thompson said:


Even if the function containing main(42) is never called? In the
OP's code, main(42) is never called. In fact, no functions are
called, except main() itself, which is called by the startup code.

Keith is making a subtle point, namely, int main(void){} is
different from int main(){}, because the first form requires
a diagnostic for any subsequent calls such as main(42),
whereas the second form does not. Whether such calls are
there in the program or not is irrelevant -- the two forms
don't behave identically, hence they are not equivalent.
 
J

jaysome

Recently I was having a chat with my friend about standard way of
writing main function in C.
We were at loggerheads about whether there are any differences between
following two methods..
int main(void)
{ }
int main()
{ }

I think both are same....
Are they?

You should always use the first, with the addition of a proper return
statement of course. Following is some additional information about
the function main.

The implementation declares no prototype for main (and you should
never declare one either). The function main can be defined with no
parameters:

int main(void) { /* ...*/ }

or with two parameters:

int main(int argc, char *argv[]) { /* ... */ }

You can use any names for the two parameters, but you're better off
using the names above, as they're more or less universally used and
recognized by novice and experienced C programmers alike.

I can think of a few reasons for using main(void) over main(). First,
the C standard specifies main(void). Second, some compilers will issue
a warning for main().

/* foo.c */
int main()
{
return 0;
}

gcc -W -Wall -ansi -pedantic -Wstrict-prototypes foo.c -o foo

foo.c:3: warning: function declaration isn't a prototype

I know this is a benign warning for the above program, but I want my
source (perhaps hundreds of files) to compile with no warnings. Rather
than use main() and live with getting the above warning every time, I
just use main(void). Even if there is no difference between the two,
it's worth it to use main(void) to eliminate such potential warnings.

A third reason for using main(void) is that it is consistent with user
function prototypes and definitions that take no parameters. Consider
the following:

/* foo1.h */
int foo1();

/* foo1.c */
int foo1()
{
return 0;
}

/* foo2.h */
int foo2(void);

/* foo2.c */
int foo2(void)
{
return 0;
}

Every function you call should have a prototype in scope (or a
definition that is equivalent to having a prototype in scope). But
foo1() is not a prototype--it is a declaration that specifies foo1
takes zero or more arguments. The declaration for foo2 is a
prototype--it is a declaration that specifies foo2 takes zero
arguments.

Notice how the definition of foo2 is exactly the same as the prototype
of foo2. That's not a coincidence, because I simply copied the line in
foo2.h and pasted it in foo2.c and removed the semicolon. In my
opinion, the semicolon should be the only difference between the
prototype and the definition text. Copy-and-paste makes this an easy
convention to follow.

Which form of main you should use depends on whether or not you need
to use the argc and argv parameters. If you don't use argc and argv, I
suggest using main(void); otherwise, you may get warnings from
compilers and tools like PC-lint about unused arguments.

int main(int argc, char *argv[])
{
return 0;
}

VC++:
warning C4100: 'argv' : unreferenced formal parameter
warning C4100: 'argc' : unreferenced formal parameter

gcc:
warning: unused parameter 'argc'
warning: unused parameter 'argv'

PC-lint:
Info 715: Symbol 'argv' (line 1) not referenced
Info 715: Symbol 'argc' (line 1) not referenced

It's better to use main(void) instead to avoid these warnings.
Following is a simple example.

#include <stdio.h>
int main(void)
{
printf("Hello world!\n");
return 0;
}

Note that the return type of main is int. Also note that the above
program returns a value of 0. Returning a value of 0 from main results
in an implementation-defined form of the status successful termination
being returned to the host environment. If your main function always
returns a success status, I suggest returning a value of 0, as above.
However, if your main function is to return an unsuccessful status,
then you should return EXIT_FAILURE, which is a macro defined in
<stdlib.h>. The latter header also defines the macro EXIT_SUCCESS,
which can be used in place of 0 to indicate successful termination. In
other words, the following program is equivalent to the one above:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("Hello world!\n");
return EXIT_SUCCESS;
}

My preference is to return 0 if main does not return EXIT_FAILURE, and
EXIT_SUCCESS if it does. Of course it does not matter whether you
return EXIT_SUCCESS or 0, but I like the parallelism by using
EXIT_FAILURE and EXIT_SUCCESS, and I may not have to include
<stdlib.h> if I only return 0. For example:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int status;
if ( argc < 2 )
{
printf("No arguments supplied\n");
status = EXIT_FAILURE;
}
else
{
printf("argv[1] is %s\n", argv[1]);
status = EXIT_SUCCESS;
}
return status;
}

If you return any value other than 0, EXIT_SUCCESS or EXIT_FAILURE
from main, the status returned is implementation-defined.

Another note about main. You can use a call to exit (declared in
<stdlib.h>) instead of using a return statement, but I suggest never
doing this (in the function main; whether you call exit in other
places is debatable). The C standard states that "a return from the
initial call to the main function is equivalent to calling the exit
function with the value returned by the main function as its
argument". The following example, although acceptable, is just plain
silly, IMHO, because of the call to exit:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if ( argc < 2 )
{
printf("No arguments supplied\n");
exit(EXIT_FAILURE);
}

printf("argv[1] is %s\n", argv[1]);
return EXIT_SUCCESS;
}

One final note about the above: it necessarily applies only to a
hosted environment. The C standard defines two execution environments:
hosted and freestanding. In a freestanding environment, the
implementation is "free" to do things such as defining main with a
return type of void or even things like using a different name other
than main for the C function that is used for program startup.

Generally speaking, you'll be using a hosted environment if you're
using a desktop OS like Linux or Windows or Mac OS and using compilers
like gcc and Visual C++ that create programs that execute within these
environments. If you ever need to be concerned with a freestanding
environment, then you'll probably have enough experience to realize
that you're working with one. Freestanding environments are popular
with embedded development.

--
jay

http://www.ubuntu.com/
http://www.microsoft.com/express/vc/
http://www.gimpel.com/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top