Discussion:
main return value is helpfull?
Add Reply
esmaeel ensanimehr
2017-04-16 19:51:17 UTC
Reply
Permalink
Raw Message
i know some work can be don on inter parameter on main function.
int main (int argc, char* argv[])

argc, argv can be used in many points.

but is there any useful example for main() return value?

for example:
int c = main();
Stefan Ram
2017-04-16 20:09:28 UTC
Reply
Permalink
Raw Message
Post by esmaeel ensanimehr
but is there any useful example for main() return value?
Yes. You can use it to signal successful termination to the
host environment!

If the value of status is zero or EXIT_SUCCESS, an
implementation-defined form of the status »successful
termination« is returned to the host environment. If the
value of status is EXIT_FAILURE, an implementation-defined
form of the status »unsuccessful termination« is returned to
the host environment.

For a simple exercise: write an implementation of the
UNIX (GNU coreutils) »true« and »false« commands.
Ben Bacarisse
2017-04-16 20:11:51 UTC
Reply
Permalink
Raw Message
Post by esmaeel ensanimehr
i know some work can be don on inter parameter on main function.
int main (int argc, char* argv[])
argc, argv can be used in many points.
but is there any useful example for main() return value?
int c = main();
That sort of use is very unusual. The most common use of the return
value from main is by the operating system. It is common for a program
to indicate that all went well by returning 0 or EXIT_SUCCESS and to
indicate a failure of some sort by returning EXIT_FAILURE. Those
constants are defined in <stdlib.h>. Some programs will even used the
return value to indicate exactly what kind of error occurred, but that
relies on knowledge of how the operating system uses the returned value.

Sticking to these conventions is useful when writing programs that are
tools to be used in what are called shell scripts.
--
Ben.
s***@casperkitty.com
2017-04-16 20:19:37 UTC
Reply
Permalink
Raw Message
Post by esmaeel ensanimehr
but is there any useful example for main() return value?
int c = main();
Many environments from which C programs can be run provide a means via which
they can indicate success or failure to the calling process. When running a
sequence of programs via shell script (Unix), batch file (DOS/Windows), or
other such means, it can be helpful to have the process stop as soon as any
part of it fails. Within MS-DOS or Windows, one could use:

Program1
IF ERRORLEVEL 1 GOTO QUIT
Program2
:QUIT

If Program1 returns zero, the system would run Program2, but if Program1
returns a value that's 1 or greater, Program2 will be skipped. Note that
in MS-DOS or Windows, the default behavior is to ignore a program's return
value unless a batch file explicitly tests it. In Unix, the default behavior
would from what I understand be to stop script processing if any program
returns a non-zero value *unless* a special syntax is used to indicate that
errors should not terminate processing.

The Standard is relatively silent as to how implementations should use the
return value, except for the general notion that if an environment provides a
means by which programs can return a value to indicate success, failure, or
other such status, it should indicate success if main() returns 0 or code
calls exit(0) and failure if main() returns 1 or code calls exit(1). If the
environment can handle more than 2 values, returning values other than 0 or 1
may be useful, but the Standard doesn't impose requirements upon how they
should work (e.g. if an environment would normally use negative values to
indicate failure and positive values to indicate success, it may be unclear
what "return 4;" should mean.
Keith Thompson
2017-04-16 21:41:15 UTC
Reply
Permalink
Raw Message
***@casperkitty.com writes:
[...]
Post by s***@casperkitty.com
The Standard is relatively silent as to how implementations should use the
return value, except for the general notion that if an environment provides a
means by which programs can return a value to indicate success, failure, or
other such status, it should indicate success if main() returns 0 or code
calls exit(0) and failure if main() returns 1 or code calls exit(1). If the
environment can handle more than 2 values, returning values other than 0 or 1
may be useful, but the Standard doesn't impose requirements upon how they
should work (e.g. if an environment would normally use negative values to
indicate failure and positive values to indicate success, it may be unclear
what "return 4;" should mean.
Returning 0 does indicate success, but the standard doesn't guarantee
that exit(1) will indicate failure. It does on many systems, but in
particular Open VMS uses odd results for success and even results for
failure (with 0 denoting success as a special case). That's why we have
the macros EXIT_SUCCESS and EXIT_FAILURE.

EXIT_SUCCESS is almost always defined as 0, but there's no requirement
that EXIT_SUCCESS==0, as long as both values denote success.

Values other than 0, EXIT_SUCCESS, or EXIT_FAILURE might have
implementation-defined meanings. For example, many programs on
Unix-like systems use other values to convey more information to the
caller. The grep command uses 1 to indicate that no match was found,
and 2 to indicate some other error; curl currently defines distinct
meanings for exit codes from 0 to 92.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Andrey Tarasevich
2017-04-17 01:58:57 UTC
Reply
Permalink
Raw Message
Post by Keith Thompson
Returning 0 does indicate success, but the standard doesn't guarantee
that exit(1) will indicate failure. It does on many systems, but in
particular Open VMS uses odd results for success and even results for
failure (with 0 denoting success as a special case). That's why we have
the macros EXIT_SUCCESS and EXIT_FAILURE.
EXIT_SUCCESS is almost always defined as 0, but there's no requirement
that EXIT_SUCCESS==0, as long as both values denote success.
The "as long as both values denote success" remark appears to be
unnecessary in this case. The specification of 'exit' states the following:

"[...] If the value of status is zero or EXIT_SUCCESS, an
implementation-defined form of the status successful termination is
returned. If the value of status is EXIT_FAILURE, an
implementation-defined form of the status unsuccessful termination is
returned. [...]"

This basically says that such status values as '0', 'EXIT_SUCCESS' and
'EXIT_FAILURE' are given special treatment. They are not necessarily
passed to the host environment _directly_. They are _translated_ into
the proper host-specific status values indicating "success" and "failure".

In other words, conceptually, the host environment never sees the actual
value of 'EXIT_SUCCESS'. It does not matter what (if anything) the value
of 'EXIT_SUCCESS' means in host environment. It is only the
implementation that sees the actual values of 'EXIT_SUCCESS'. And it
guarantees that 'exit(EXIT_SUCCESS)' will return to the host a [possibly
different] status code indicating "success".

If some host environment uses values of '-1' and '255' to indicate
"failure" and "success", it still perfectly possible to have
'EXIT_FAILURE' defined as '1' and 'EXIT_SUCCESS' defined as '0', as long
as 'exit' remembers to translate '1' to '-1' and '0' to '255'.
--
Best regards,
Andrey Tarasevich
Manfred
2017-04-17 17:34:52 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
If Program1 returns zero, the system would run Program2, but if Program1
returns a value that's 1 or greater, Program2 will be skipped. Note that
in MS-DOS or Windows, the default behavior is to ignore a program's return
value unless a batch file explicitly tests it. In Unix, the default behavior
would from what I understand be to stop script processing if any program
returns a non-zero value*unless* a special syntax is used to indicate that
errors should not terminate processing.
GNU bash (and sh variant) script processing is /not/ stopped by default
in case of failure of any program. Do you mean that Unix would be
different? (not, as far as I know)
Lew Pitcher
2017-04-17 17:57:15 UTC
Reply
Permalink
Raw Message
Post by s***@casperkitty.com
Post by esmaeel ensanimehr
but is there any useful example for main() return value?
int c = main();
Many environments from which C programs can be run provide a means via which
they can indicate success or failure to the calling process. When running
a sequence of programs via shell script (Unix), batch file (DOS/Windows),
or other such means, it can be helpful to have the process stop as soon as
any part of it fails.
[snip]
Post by s***@casperkitty.com
In Unix, the default
behavior would from what I understand be to stop script processing if any
program returns a non-zero value *unless* a special syntax is used to
indicate that errors should not terminate processing.
Nonsense.

Unix shell scripting languages have a well-defined behaviour wrt evaluating
the return value from a process.
1) Unless explicitly tested, the return value (no matter what it is) is
ignored.
2) When explicitly tested, a return value of zero (0) is treated as an
indication of success. A non-zero value is /not/ an explicit indication
of failure.

3) The script may test for a specific return value, and take action
accordingly.


Consequently, the following is valid...

cat >test_1.c <<EOF
int main(void) { return 0; }
EOF
if cc -o test_1 test_1.c
then
test_1
else
echo Compilation returned a non-zero rc
fi

where cat, cc, and test_1 are all programs that return "return values" to
the script.

[snip]
--
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request
Keith Thompson
2017-04-17 19:19:04 UTC
Reply
Permalink
Raw Message
Lew Pitcher <***@digitalfreehold.ca> writes:
[...]
Post by Lew Pitcher
Unix shell scripting languages have a well-defined behaviour wrt evaluating
the return value from a process.
1) Unless explicitly tested, the return value (no matter what it is) is
ignored.
There's an option (`set -e`) to terminate the script if a command fails,
but it's not set by default.
Post by Lew Pitcher
2) When explicitly tested, a return value of zero (0) is treated as an
indication of success. A non-zero value is /not/ an explicit indication
of failure.
It depends on how you test it. For example, the shell's "if" statement
treats a return value of 0 as success/true, and any non-zero return
value as failure/false.

(This is for sh-derived shells, including sh, bash, zsh, kshd.
It doesn't necessarily apply to csh, tcsh, fish, etc.)
Post by Lew Pitcher
3) The script may test for a specific return value, and take action
accordingly.
Yes.

[...]
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Manfred
2017-04-18 11:03:28 UTC
Reply
Permalink
Raw Message
Post by Keith Thompson
Post by Lew Pitcher
2) When explicitly tested, a return value of zero (0) is treated as an
indication of success. A non-zero value is/not/ an explicit indication
of failure.
It depends on how you test it. For example, the shell's "if" statement
treats a return value of 0 as success/true, and any non-zero return
value as failure/false.
This is probably best expressed as the shell, when converting to
boolean, mapping zero to true, and nonzero to false. The notion of
success/failure might suggest consequences that are in fact left under
control of the script writer.
Keith Thompson
2017-04-18 16:29:40 UTC
Reply
Permalink
Raw Message
Post by Manfred
Post by Keith Thompson
Post by Lew Pitcher
2) When explicitly tested, a return value of zero (0) is treated as an
indication of success. A non-zero value is/not/ an explicit indication
of failure.
It depends on how you test it. For example, the shell's "if" statement
treats a return value of 0 as success/true, and any non-zero return
value as failure/false.
This is probably best expressed as the shell, when converting to
boolean, mapping zero to true, and nonzero to false. The notion of
success/failure might suggest consequences that are in fact left under
control of the script writer.
The way I'd describe it is that the shell's "if" statement (unlike
C's "if" statement) makes its decision based on whether the command
succeeds or fails rather than truth vs. falsehood.

That's why there's a "true" command that always succeeds,and a
"false" command that always fails, along with a "test" command that
evaluates an expression and then succeeds if it's true or fails
if it's false. If you have a true/false condition, you have to
convert it to a success/failure status in order to use it with "if".

The shell's use of zero for success and any non-zero value for
failure can be a little confusing, since it's seemingly the opposite
of C's use of zero for false and non-zero for true. The reason
is that typically there's only one way for a command to succeed,
and multiple ways it can fail.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Gordon Burditt
2017-04-17 09:40:00 UTC
Reply
Permalink
Raw Message
Post by esmaeel ensanimehr
i know some work can be don on inter parameter on main function.
int main (int argc, char* argv[])
argc, argv can be used in many points.
but is there any useful example for main() return value?
Return values from main() are used a lot by the invoking program
(which it can get from the operating system). The actual C code to
do that in UNIX/POSIX might be:
int pid;
int status;

pid = wait(&status);

where pid is the process ID of the process that terminated, and
status is filled in with a combination of what signal the process
died on (if it was aborted) and 8 bits of the return value (if it
terminated normally). There are some cute macros to separate out
the parts of the status. There are additional complications if job
control is in use (the process may return status if it changes state
due to job control signals without actually terminating).

(or it might look at the return code from the system() function.)

Shell scripts (examples are for the Bourne shell and descendants)
can get hold of the return value in the value $?, or test success/failure
with the construct:

if command args ...
then
: execute here if it succeeded (exit 0)
else
: execute here if it failed (exit non-zero)
fi

The "make" program will generally stop running a build if any command
it invoked returns non-zero status, although you can exempt specific
commands from this treatment so conditional code can be used in
build scripts.

The front-end for the compiler (if that's how the compiler is
organized) will typically stop further operations if a stage earlier
in the compilation (preprocessing, compiling, assembling, linking)
typically done as a separate process fails. Some compilers may use
a code between its components to indicate differences between
warnings (which normally don't halt compilation; -Werror on GCC is
an exception), errors (e.g. syntax errors in the program), bad
errors (e.g. can't open the input source file, or running out of
disk space writing the object file, compiler errors, and running
out of memory), and really bad errors (e.g. pieces of the compiler
are missing).

There are some unofficial standards for file comparison and file
searching programs which use a 3-way status. This tends to twist
the definitions of "success" and "failure" a little. File comparison
programs include cmp, diff, rcsdiff, etc. File search programs
include grep, egrep, and fgrep. The C standard doesn't allow for
degrees of failure, and there are no required definitions for symbols
like:

EXIT_SUCCESS_WITH_PROMOTION_AND_RAISE
EXIT_SUCCESS_YOU_GET_TO_KEEP_YOUR_JOB
EXIT_FAILURE_YOU_ARE ARRESTED
EXIT_FAILURE_YOU_ARE_EXECUTED

On UNIX, EXIT_SUCCESS is 0 and EXIT_FAILURE is 1.

File comparison programs:
0 - success; files are equal.
1 - success; files are NOT equal. (some people will argue this is a failure).
2 - trouble; the comparison could not be done due to nonexistent
files, file permission problems, I/O errors, or a host of other
problems. An error message should indicate the reason.

File search programs:
0 - success; search pattern found.
1 - success; search pattern NOT found. (some people will argue this is a failure).
2 - trouble; the search could not be done due to nonexistent files, file
permission problems, bad search parameters (bad regular expression),
I/O errors, or a host of other problems. An error message
should indicate the reason.

Here 1, which is the value of EXIT_FAILURE on UNIX, is used as a
lesser success code. I can think of situations where "files are
equal" is a failure in the larger view of things (e.g. the patch
failed to take), and plenty of situations where NOT finding the
string I'm looking for is not some kind of disastrous error.

There are a lot of little utility programs for use with shell
scripts, and some of them do very little BUT set the return code.
See, for example, the UNIX "test" program which can be used to
determine if a file exists, or the type of an object in the filesystem
(nonexistent, regular file, directory, socket, special device file,
FIFO, etc.) or test the relative order of file timestamps.

Mail delivery programs often follow an unofficial standard of
returning one of the codes in <sysexits.h> to indicate an error.
The error codes are oriented towards typical mail-delivery and
networking errors (e.g. host not found, host unreachable, unknown
user, etc.)
Joe Pfeiffer
2017-04-19 03:39:44 UTC
Reply
Permalink
Raw Message
Post by esmaeel ensanimehr
i know some work can be don on inter parameter on main function.
int main (int argc, char* argv[])
argc, argv can be used in many points.
but is there any useful example for main() return value?
int c = main();
If I ever saw something like that occur in a piece of code, I'd know I'd
be looking at a long, painful time trying to figure out what the overly
clever author was doing. That's really not the purpose of the return
value of main().

What I've seen it used for in many places is looking at the return value
of a program (which is returned by the return value of main()); at its
simplest it can be used to tell whether the program executed
successfully, and in other cases can be used to return a useful value to
the shell.

Loading...