Why is argc not a constant? - c++

int main( const int argc , const char[] const argv)
As Effective C++ Item#3 states "Use const whenever possible", I start thinking "why not make these 'constant' parameters const"?.
Is there any scenario in which the value of argc is modified in a program?

In this case, history is a factor. C defined these inputs as "not constant", and compatibility with (a good portion of) existing C code was an early goal of C++.
Some UNIX APIs, such as getopt, actually do manipulate argv[], so it can't be made const for that reason also.
(Aside: Interestingly, although getopt's prototype suggests it won't modify argv[] but may modify the strings pointed to, the Linux man page indicates that getopt permutes its arguments, and it appears they know they're being naughty. The man page at the Open Group does not mention this permutation.)
Putting const on argc and argv wouldn't buy much, and it would invalidate some old-school programming practices, such as:
// print out all the arguments:
while (--argc)
std::cout << *++argv << std::endl;
I've written such programs in C, and I know I'm not alone. I copied the example from somewhere.

The C standard (ISO/IEC 9899:2011) says:
5.1.2.2.1 Program startup
¶1 The function called at program startup is named main. The implementation declares no
prototype for this function. It shall be defined with a return type of int and with no
parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be
used, as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;10) or in some other implementation-defined manner.
¶2 If they are declared, the parameters to the main function shall obey the following
constraints:
The value of argc shall be nonnegative.
argv[argc] shall be a null pointer.
If the value of argc is greater than zero, the array members argv[0] through
argv[argc-1] inclusive shall contain pointers to strings, which are given
implementation-defined values by the host environment prior to program startup. The
intent is to supply to the program information determined prior to program startup
from elsewhere in the hosted environment. If the host environment is not capable of
supplying strings with letters in both uppercase and lowercase, the implementation
shall ensure that the strings are received in lowercase.
If the value of argc is greater than zero, the string pointed to by argv[0]
represents the program name; argv[0][0] shall be the null character if the
program name is not available from the host environment. If the value of argc is
greater than one, the strings pointed to by argv[1] through argv[argc-1]
represent the program parameters.
The parameters argc and argv and the strings pointed to by the argv array shall
be modifiable by the program, and retain their last-stored values between program
startup and program termination.
10) Thus, int can be replaced by a typedef name defined as int, or the type of argv can be written as
char **argv, and so on.
Note the last bullet point. It says that both argc and argv should be modifiable. They don't have to be modified, but they may be modified.

argc is not normally a constant because the function signature for main() pre-dates const.
Since argc is a stack variable, changing it won't affect anything other than your own command line processing.
You are, of course, free to declare it const if you want.

A top level const on a formal argument is not part of the function type. You can add it or remove it as you like: it only affects what you can do with the argument in the function implementation.
So for argc you can add freely add a const.
But for argv you can not make the character data const without thereby changing the function signature. Which means that it's then not one of the standard main function signatures, and will not have to be recognized as a main function. So, not a good idea.
A good reason for not using the standard main arguments in non-toy programs is that in Windows they are not able to represent actual program arguments such as filenames with international characters. That's because in Windows they are by very strong convention encoded as Windows ANSI. In Windows you can implement some more portable argument access facility in terms of the GetCommandLine API function.
Summing up, nothing prevents you from adding const to argc, but the most useful const-ness on argv would give you a non-standard main function, most probably not recognized as such. Happily (in an ironic way) there are good reason to not use the standard main arguments for portable serious code. Quite simply, for the in-practice they only support old ASCII, with only English alphabet letters.

The signature of main is somewhat of a historical artifact from C. Historically C did not have const.
However, you can declare your parameter const since the effects of const are compile time only.

Because argc is a local variable (and, in C++, not a reference or something), and because the special place of main means that backwards compatibility shenanigans grant it a huge amount of leeway with no compelling reason to force applications to make it const.
main() {}
int main() {}
main() { return 0; }
main(int argc, char* argv[]) { return 0; }
int main(const int argc, const char** argv) { /* no return*/ }
these and many other variations will compile on a wide range of C and C++ compilers.
So ultimately it's not that argc isn't const, just that it doesn't have to be, but it can be if you want it to be.
http://ideone.com/FKldHF, C example:
main(const int argc, const char* argv[]) { return 0; }
http://ideone.com/m1qc9c, C++ example
main(const int argc) {}

Aside from the historical reasons, a good reason to keep argc and argv non-const is that the compiler implementation doesn't know what you're going to do with the arguments to main, it just knows that it must give you those arguments.
When you are defining your own functions and associated prototypes, you know which parameters you can make const and which ones your function will modify.
Taken to an extreme, you could declare that all parameters to all functions should be declared const, and then if you had a reason to change them (e.g. decrement an index to search through an array), you'd have to make local non-const variables and copy the const arguments' values into those variables. That makes for busy-work and extra LOC with no real benefit. A decent static analyzer will pick up if you're not modifying the value of an argument, and recommend that you make the parameter const.

Related

why does my code sayserror: ld returned 1 exit status? [duplicate]

Questions
What is the proper signature of the main function in C++?
What is the correct return type, and what does it mean to return a value from main?
What are the allowed parameter types, and what are their meanings?
Is this system-specific?
Have those rules changed over time?
What happens if I violate them?
The main function must be declared as a non-member function in the global namespace. This means that it cannot be a static or non-static member function of a class, nor can it be placed in a namespace (even the unnamed namespace).
The name main is not reserved in C++ except as a function in the global namespace. You are free to declare other entities named main, including among other things, classes, variables, enumerations, member functions, and non-member functions not in the global namespace.
You can declare a function named main as a member function or in a namespace, but such a function would not be the main function that designates where the program starts.
The main function cannot be declared as static or inline. It also cannot be overloaded; there can be only one function named main in the global namespace.
The main function cannot be used in your program: you are not allowed to call the main function from anywhere in your code, nor are you allowed to take its address.
The return type of main must be int. No other return type is allowed (this rule is in bold because it is very common to see incorrect programs that declare main with a return type of void; this is probably the most frequently violated rule concerning the main function).
There are two declarations of main that must be allowed:
int main() // (1)
int main(int, char*[]) // (2)
In (1), there are no parameters.
In (2), there are two parameters and they are conventionally named argc and argv, respectively. argv is a pointer to an array of C strings representing the arguments to the program. argc is the number of arguments in the argv array.
Usually, argv[0] contains the name of the program, but this is not always the case. argv[argc] is guaranteed to be a null pointer.
Note that since an array type argument (like char*[]) is really just a pointer type argument in disguise, the following two are both valid ways to write (2) and they both mean exactly the same thing:
int main(int argc, char* argv[])
int main(int argc, char** argv)
Some implementations may allow other types and numbers of parameters; you'd have to check the documentation of your implementation to see what it supports.
main() is expected to return zero to indicate success and non-zero to indicate failure. You are not required to explicitly write a return statement in main(): if you let main() return without an explicit return statement, it's the same as if you had written return 0;. The following two main() functions have the same behavior:
int main() { }
int main() { return 0; }
There are two macros, EXIT_SUCCESS and EXIT_FAILURE, defined in <cstdlib> that can also be returned from main() to indicate success and failure, respectively.
The value returned by main() is passed to the exit() function, which terminates the program.
Note that all of this applies only when compiling for a hosted environment (informally, an environment where you have a full standard library and there's an OS running your program). It is also possible to compile a C++ program for a freestanding environment (for example, some types of embedded systems), in which case startup and termination are wholly implementation-defined and a main() function may not even be required. If you're writing C++ for a modern desktop OS, though, you're compiling for a hosted environment.
From Standard docs., 3.6.1.2 Main Function,
It shall have a return
type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following
definitions of main:
int main() { / ... / } and
int main(int argc, char* argv[]) { / ... / }
In the latter form argc shall be the number of arguments passed to the program from the environment in which the
program is run.If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to
the initial characters of null-terminated multibyte strings.....
Hope that helps..
The exact wording of the latest published standard (C++14) is:
An implementation shall allow both
a function of () returning int and
a function of (int, pointer to pointer to char) returning int
as the type of main.
This makes it clear that alternative spellings are permitted so long as the type of main is the type int() or int(int, char**). So the following are also permitted:
int main(void)
auto main() -> int
int main ( )
signed int main()
typedef char **a; typedef int b, e; e main(b d, a c)
The two valid mains are int main() and int main(int, char*[]). Any thing else may or may not compile. If main doesn't explicitly return a value, 0 is implicitly returned.
Details on return values and their meaning
Per 3.6.1 ([basic.start.main]):
A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control reaches the end of main without encountering a return statement, the effect is that of executing
return 0;
The behavior of std::exit is detailed in section 18.5 ([support.start.term]), and describes the status code:
Finally, control is returned to the host environment. If status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.

Does Main() accept expression?

Why this code prints 1 instead of 5
Code:
main(int x=5) //this defn. is written intentionally to chec weather main accepts
expression or not.
{
printf("%d",x);
}
Compiler used:minGW 3.2
EDIT
My point is weather x=5 executes or not. if not then why i don't get any error or warning.
because x is really argc (and your count of arguments is 1)
The signature for main is:
int main (int argc, char **argv)
with argc being a count of arguments
and argv being an array of those arguments
In void f(int x = 5), the = 5 part is a default argument. You can call the function in two different ways:
f(); // uses default argument, as if f(5)
f(3); // explicit argument
Note that the decision to use the default argument is made at the point of the call, not at the point of the declaration. Regardless of whether int main(int x = 5, char *argv[]) is valid, the application's startup code (part of the compiler's library) won't know about the attempted default argument, so won't do anything with it. And don't try and get tricky by calling main from inside your program: that's not allowed.
Update
Your main declaration is not valid, if we look at the C++ draft standard section 3.6.1 Main function paragraph 2 says(emphasis mine):
An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both
— a function of () returning int and
— a function of (int, pointer to pointer to char) returning int
So main should adhere to one of these standard forms or implementation defined forms defined by compiler documentation.
gcc gives me a warning for this regardless of warning levels and in clang this is an error, so I am not sure why you do not see an error.
Orignal Answer
The first argument to main is the argument count usually denoted as argc for example:
int main(int argc, char *argv[])
{
}
and argv is an array of string which represents the arguments to your program, the first one being the command line.
Because the operating system expects this signature of main:
int main(int argc, char** argv);
argc is the amount of parameters. When it calls your main, it passes the amount of arguments (argc) as the first parameter, which is 1 (if you call your binary without arguments, you still get one argument: the binary filename, $0 in bash).
Note that this depends also on the C ABI. By the C/C++ standard, multiple signatures of main are allowed. So, depending on the compiler and the OS, there could be a different handling for main. What you are doing is not really defined behavior.
You should declare main like the expected - because that is what your OS expects and uses. Make another function for whatever you want to program.

What happens if main() does not return an int value?

I know that in C compilers the main() function is called by the _start() function which has code something like this:
exit(main()); // return value of main is returned
How does _start() work when main() does not return int, for example if its return type is void, float, or something else?
If main doesn't return int, then you have an ill-formed program and behavior is undefined. Anything can happen. Your program might crash, or it might run as though nothing were wrong at all.
Let's suppose main returned something other than int, and your compiler and linker allowed the program to be made. The caller doesn't know that, though. If the caller expects returned int values to be returned in the EAX (Intel) register, then that's what it will read to determine the return value of main. If your faulty main stored a float value there, then it will be interpreted as an int instead. (That doesn't mean it will get truncated. It means the bits making up the layout of a floating-point value will instead make up an int instead.) If your faulty main returned void, then it didn't store anything in the expected register, so the caller will get whatever value was previously stored in that register instead.
If your main returns some type that it expects to store someplace that the caller didn't' reserve memory for (such as a large struct), then it will end up overwriting something else, perhaps something important to the clean shutdown of the program, causing your program to crash.
The C standard never mentions this _start function; I don't believe C++ does either.
In C prior to the 1999 ISO standard, if execution reaches the end of main() without executing a return statement, or executes a return statement that doesn't specify a value, then "the termination status returned to the host environment is undefined". In practice, I've seen implementations where such a program returns a status of 1 (failure), or some arbitrary value in memory such as the result of the last function that was called.
The 1999 ISO C standard changed this: "reaching the } that terminates the main function returns a value of 0". This matches the rule that C++ has had at least since the first ISO C++ standard in 1998.
(As a matter of style, I prefer to have an explicit return 0; at the end of main, even if it's not strictly required. This is consistent with int functions other than main, and it makes for better portability to pre-C99 C compilers.)
All this assumes that main is defined with a return type of int. That's the only type that's specifically supported by the C standard (either int main(void) or int main(int argc, char *argv[]) or equivalent), but (hosted) implementations may support other implementation-defined definitions. The C90 standard doesn't explicitly cover this case, but C99 says, "If the return type is not compatible with int, the termination status returned to the host environment is unspecified."
The C++ standard is a bit different. For hosted implementations, main must be defined to return int. The parameters are implementation-defined, but both the standard forms of C must be supported.
For a hosted implementation in either C or C++, there is no good reason I know of to define main with a return type other than int. Just use one of the two standard definitions, and the question won't arise.
For "freestanding implementations", "the name and type of the function called at program
startup are implementation-defined". So the entry point might legitimately return void or something else, and it might not even be called main. Note that a "freestanding implementation" is one "in which C program execution may take place without any
benefit of an operating system", typically an embedded system.
The function will return an implementation-defined value. For example, in C++, main implicitly returns 0. In this case of a void main then this would simply be returned by _start. However, there are virtually no implementations that would allow any arbitrary return type- it's baked into the operating system that a process exits with an integral value.
In C++ it would be a compile error to return anything other than int from main():
error: ‘::main’ must return ‘int’
In C it is a warning, you will get a float reinterpreted as an int: for example, 2.1F would be reinterpreted as 224.
Standard implementations of C expect main to return int just because it is defined that way in the C standard. Returning something other than int (or a type compatible with int) usually results in undefined behaviour—meaning there is no way to tell what will happen.
However, there are non-standard implementations of C, for example, the Plan 9 operating system uses void main(), here is a list their utilities&apos; source code. Plan 9 C code is quite a bit different to K&R, ANSI, C99 or C11. Here's a link explaining how Plan 9 uses the C language.
If the return type of main is not an int then the return value is implementation defined.
In short an Implementation is allowed to have different return type than int for main but none of the known implementations support anything other than int.
Ideally, You will need to refer to the documentation of your platform and the compiler to see what exact behavior it defines because it is allowed to have the flexibility do so by the standard.
Reference:
C++03 Standard:
3.6.1 Main function [basic.start.main]
An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following definitions of main:
int main() { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }
.....
The C-standard does not allow you to return any other value than int or void -- the c-compiler specifically test for the signature of main to make sure it is compatible.
Assume we're using Visual Studio 2012.
For C++ programs, Visual Studio allows void to be specified as the return type, even though this is forbidden by the C++ standard. Under the standard, main() must return an int in hosted implementations.
For C programs, any return type is allowed for main(), but returning something other than an int results in unspecified behavior. For example, under Visual Studio 2012, returning 0.0 from double main() results in a return value of 0xcccccccc when the program is run in the debugger (see In Visual Studio C++, what are the memory allocation representations?).

What is the proper declaration of main in C++?

Questions
What is the proper signature of the main function in C++?
What is the correct return type, and what does it mean to return a value from main?
What are the allowed parameter types, and what are their meanings?
Is this system-specific?
Have those rules changed over time?
What happens if I violate them?
The main function must be declared as a non-member function in the global namespace. This means that it cannot be a static or non-static member function of a class, nor can it be placed in a namespace (even the unnamed namespace).
The name main is not reserved in C++ except as a function in the global namespace. You are free to declare other entities named main, including among other things, classes, variables, enumerations, member functions, and non-member functions not in the global namespace.
You can declare a function named main as a member function or in a namespace, but such a function would not be the main function that designates where the program starts.
The main function cannot be declared as static or inline. It also cannot be overloaded; there can be only one function named main in the global namespace.
The main function cannot be used in your program: you are not allowed to call the main function from anywhere in your code, nor are you allowed to take its address.
The return type of main must be int. No other return type is allowed (this rule is in bold because it is very common to see incorrect programs that declare main with a return type of void; this is probably the most frequently violated rule concerning the main function).
There are two declarations of main that must be allowed:
int main() // (1)
int main(int, char*[]) // (2)
In (1), there are no parameters.
In (2), there are two parameters and they are conventionally named argc and argv, respectively. argv is a pointer to an array of C strings representing the arguments to the program. argc is the number of arguments in the argv array.
Usually, argv[0] contains the name of the program, but this is not always the case. argv[argc] is guaranteed to be a null pointer.
Note that since an array type argument (like char*[]) is really just a pointer type argument in disguise, the following two are both valid ways to write (2) and they both mean exactly the same thing:
int main(int argc, char* argv[])
int main(int argc, char** argv)
Some implementations may allow other types and numbers of parameters; you'd have to check the documentation of your implementation to see what it supports.
main() is expected to return zero to indicate success and non-zero to indicate failure. You are not required to explicitly write a return statement in main(): if you let main() return without an explicit return statement, it's the same as if you had written return 0;. The following two main() functions have the same behavior:
int main() { }
int main() { return 0; }
There are two macros, EXIT_SUCCESS and EXIT_FAILURE, defined in <cstdlib> that can also be returned from main() to indicate success and failure, respectively.
The value returned by main() is passed to the exit() function, which terminates the program.
Note that all of this applies only when compiling for a hosted environment (informally, an environment where you have a full standard library and there's an OS running your program). It is also possible to compile a C++ program for a freestanding environment (for example, some types of embedded systems), in which case startup and termination are wholly implementation-defined and a main() function may not even be required. If you're writing C++ for a modern desktop OS, though, you're compiling for a hosted environment.
From Standard docs., 3.6.1.2 Main Function,
It shall have a return
type of type int, but otherwise its type is implementation-defined. All implementations shall allow both of the following
definitions of main:
int main() { / ... / } and
int main(int argc, char* argv[]) { / ... / }
In the latter form argc shall be the number of arguments passed to the program from the environment in which the
program is run.If argc is nonzero these arguments shall be supplied in argv[0] through argv[argc-1] as pointers to
the initial characters of null-terminated multibyte strings.....
Hope that helps..
The exact wording of the latest published standard (C++14) is:
An implementation shall allow both
a function of () returning int and
a function of (int, pointer to pointer to char) returning int
as the type of main.
This makes it clear that alternative spellings are permitted so long as the type of main is the type int() or int(int, char**). So the following are also permitted:
int main(void)
auto main() -> int
int main ( )
signed int main()
typedef char **a; typedef int b, e; e main(b d, a c)
The two valid mains are int main() and int main(int, char*[]). Any thing else may or may not compile. If main doesn't explicitly return a value, 0 is implicitly returned.
Details on return values and their meaning
Per 3.6.1 ([basic.start.main]):
A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling std::exit with the return value as the argument. If control reaches the end of main without encountering a return statement, the effect is that of executing
return 0;
The behavior of std::exit is detailed in section 18.5 ([support.start.term]), and describes the status code:
Finally, control is returned to the host environment. If status is zero or EXIT_SUCCESS, an implementation-defined form of the status successful termination is returned. If status is EXIT_FAILURE, an implementation-defined form of the status unsuccessful termination is returned. Otherwise the status returned is implementation-defined.

Can the arguments of main's signature in C++ have the unsigned and const qualifiers? [duplicate]

This question already has answers here:
What should main() return in C and C++?
(19 answers)
Closed 5 years ago.
The standard explicitly states that main has two valid (i.e., guaranteed to work) signatures; namely:
int main();
int main(int, char*[]);
My question is simple, would something like the following be legal?
int main(const unsigned int, const char* const* argv);
My tests say 'yes', but I'm unsure of the answer because am I not overloading main by changing int to unsigned int as well as the non top-level const-ness of argv? If I am, then that's clearly prohibited.
So, are these modifications guaranteed to work on a standards conforming compiler?
The C++98 standard says in section 3.6.1 paragraph 2
An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both the following definitions of main: int main() and int main(int argc, char* argv[])
So it's not mandated by the standard that the env accepting main is acceptable but it is permissible.
Because this is referred to often, here is the previous paragraph exempting freestanding environments from anything but documenting their behavior:
A program shall contain a global function called main, which is the designated start of the program. It is
implementation defined
whether a program in a freestanding environment is required to define a main
function. [Note: in a freestanding environment, startup
and termination is implementation defined;
startup
contains the execution of constructors for objects of namespace scope with static storage duration; termination
contains the execution of destructors for objects with static storage duration. ]
You must use one of the standard-conformant signatures to be standard-conformant.
I fully understand why you want to do it your way. The best way is to write your own function myMain() or whatever with the signature you want and call it from main(), including the required casts.
The argv pointers shouldn't be const char* const because the program is allowed to change the buffers.
As far as I can see from reading the standard, you're being non-standards-compliant. But I can't imagine a compiler that wouldn't let you do this. As in, it'd take more work from the compiler to specifically ban an edge case that is mostly harmless and very obscure.
This may not work if the compiler uses name mangling for main. It's a C++ function after all. Hence, the linker will be looking for two particular "manglings". Your definition would have another mangled name.
Note that main is special (doesn't overload, not callable) and might not require name mangling at all.
You might be illegal by the standard, but most runtimes don't really care. They'll just push an integer for argc and a pointer for argv, call your main, and hope you parse them right. So, in your purview, "guaranteed to work" is debatable as the loader really doesn't care what you've declared the arguments as.
If it builds, main will get called. How you parse the arguments is up to you. I should clarify that this is highly platform-specific, as is nearly this entire question.
That said, why?
ISO/IEC 9899:TC3
Section 5.1.2.2.1 Program startup
The function called at program startup is named main. The implementation declares no
prototype for this function. It shall be defined with a return type of int and with no
parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be
used, as they are local to the function in which they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;9) or in some other implementation-defined manner.