Is this a valid definition for main() - c

The C11 Standard declares that:
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; 10), or in some other implementation-defined manner.
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.
We will ignore this part: or in some other implementation-defined manner. since I'm interested only in definitions equivalent to the two above examples.
Would this be a valid definition for main since char* a[4] and char** are equivalent:
int main(int argc, char* argv[4]){/*...*/}
How about a VLA array, we are assuming printf will return a positive int value:
int main(int argc, char* argv[printf("Hello there!")]){/*...*/}

Yes, this is all covered by the "or equivalent". The footnote about renaming parameters or using typedefed types are just examples.
My favorite variant is
int main(int argc, char* argv[argc+1]){/*...*/}
because it has the most information about the semantic of all main functions.

int main(int argc, char* argv[4]){/*...*/}
is a valid signature of main. Compiler will ignore 4 in char argv[4] and it is equivalent to char argv[] = char **argv. Same goes with second signature.

Related

Defining main with constant arguments (const int argc, const char * const argv[])?

In glibc, main is documented as either,
int main (int argc, char *argv[])
Or,
int main (int argc, char *argv[], char *envp[])
Can you define all the arguments as being const if you don't want to change them?
int main (const int argc, const char * const argv[])
Is it supported, unsupported, or illegal?
In C, the implementation is allowed to support basically any type for the main function, so it may very well be that your particular implementation allows the various forms you have proposed. (And indeed it seems to allow the three-parameter version that exposes the environment.) However, the implementation is only required to accept the two forms
int main(void)
and
int main(int, char**)
Since int(int, const char**) isn't the same type as int(int, char**), your proposed "constified" version is not strictly speaking required to be supported and falls under the first rule. It is, however, quite likely to work since char* and const char* are laid out the same way as far as the ABI is concerned, and the data you're given is mutable anyway.
Note further that int f(int) and int f(const int) are the same identical prototype, so there is no problem here regarding top-level qualifications of the parameters.

how string (command line) are stored in char**argv and int *argv?

First snippet:
#include<stdio.h>
int main(int argc, char **argv)
{
int i;
for(i=1; i<argc; i++)
printf("%s\n", argv[i]);
return 0;
}
load time input :
./a.out devang samir
output:
devang
samir
Second snippet:
#include<stdio.h>
int main(int argc, int *argv)
{
int i;
for(i=1; i<argc; i++)
printf("%s\n", argv[i]);
return 0;
}
load time input :
./a.out devang samir
output:
devang
samir
in both case, i got output same, but why?
in first case how the strings (command line ) are stored in char** argv ?
in second case how the string (command line ) are stored in int * argv...?
The C11 standard specifies the function signature for main() in chapter §5.1.2.2.1 as
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;[...]
and regarding the constrains,
If the value of argc is greater than zero, the array members argv[0] through
argv[argc-1] inclusive shall contain pointers to strings,[...]
Then, in your second case,
int main(int argc, int *argv)
char* and int ( for argv[n], in general) are being different types altogether (i.e, not compatible type), your second program invokes undefined behavior.
To elaborate, in case of the functions without having a prototype, the parameters passed to the function while calling should exactly match the type of expected arguments.
Quoting the standard, chapter §6.5.2.2
[...] If the function is defined with a type that does not include a prototype, and the types of
the arguments after promotion are not compatible with those of the parameters after
promotion, the behavior is undefined.

List environment variables with C

I have used the below code to print the environmental variables.In that I have doubt is there a connection between the parameters of char *argv[] and char *envp[] in main function.
Sample Code:-
#include <stdio.h>
int main(int argc, char *argv[], char *envp[])
{
int index = 0;
while (envp[index])
printf("%s\n", envp[index++]);
}
While executing the program after removed the arguments argc and argv I get segmentation fault.
Some one please explain this.!
It doesn't matter what the arguments are called; only their position matters.
If you removed argc and argv, and so you only have
int main(char *envp[])
this is illegal (since the first argument should be an integer).
What is the problem with including argc and argv, but not using them?
Also, I should point out that envp is not portable. But it is accepted by the most widely used C implementations.
main is called int main(int argc, char** argv, char** envp).
If you remove argc, argv, it will be
int main(char* envp[])
so envp will be set to argc, and there will be segmentation fault when envp[index++]

How to access argv[] from outside the main() function?

I happen to have several functions which access different arguments of the program through the argv[] array. Right now, those functions are nested inside the main() function because of a language extension the compiler provides to allow such structures.
I would like to get rid of the nested functions so that interoperability is possible without depending on a language extension.
First of all I thought of an array pointer which I would point to argv[] once the program starts, this variable would be outside of the main() function and declared before the functions so that it could be used by them.
So I declared such a pointer as follows:
char *(*name)[];
Which should be a pointer to an array of pointers to characters. However, when I try to point it to argv[] I get a warning on an assignment from an incompatible pointer type:
name = &argv;
What could be the problem? Do you think of another way to access the argv[] array from outside the main() function?
char ** name;
...
name = argv;
will do the trick :)
you see char *(*name) [] is a pointer to array of pointers to char. Whereas your function argument argv has type pointer to pointer to char, and therefore &argv has type pointer to pointer to pointer to char. Why? Because when you declare a function to take an array it is the same for the compiler as a function taking a pointer. That is,
void f(char* a[]);
void f(char** a);
void f(char* a[4]);
are absolutely identical equivalent declarations. Not that an array is a pointer, but as a function argument it is
HTH
This should work,
char **global_argv;
int f(){
printf("%s\n", global_argv[0]);
}
int main(int argc, char *argv[]){
global_argv = argv;
f();
}
#include <stdio.h>
int foo(int pArgc, char **pArgv);
int foo(int pArgc, char **pArgv) {
int argIdx;
/* do stuff with pArgv[] elements, e.g. */
for (argIdx = 0; argIdx < pArgc; argIdx++)
fprintf(stderr, "%s\n", pArgv[argIdx]);
return 0;
}
int main(int argc, char **argv) {
foo(argc, argv);
}

Passing arguments to a C program

I was writing a C program where I use 6 variables a,b,c,d,e,f
a,b,c are constant values which I should pass as an arguments from the command line.
d,e,f are going to be size of arrays of a structure.
typedef struct
{
blah blah
} ex;
ex ex0[d];
I am very confused about how to pass all these as argument. Right now I have hard coded these values,which apparently I should not be doing.
This should get you started:
int main(int argc, char* argv[]) {
// argc - number of command line arguments
// argv - the comand line arguments as an array
return 0;
}
All params you pass to the program are stored in second argument of main function
int main(int argc, char* argv[]) // or int main(argc, char** argv)
so you can easily access 4th parameter by argc[3]. But it is not int, it is string, so you need to parse it. There are standard libraries for both taking you actual parameters from argc and parsing them for type you need. But in casual progrmas there is no point using them, so your code may look like this:
typedef struct
{
blah blah
} ex;
int main(int argc, char* argv[])
{
ex ex0[(int)argv[3]]; // i am not sure if it works on pure C, so you can try int atoi(char *nptr) from stdlib.h
}
Use command line arguments
int main(int argc, char* argv[]) // or int main(int argc, char **argv)
{
// argc is the argument count
//argv : The array of character pointers is the listing of all the arguments.
//argv[0] is the name of the program.
//argv[argc] is a null pointer
}

Resources