List environment variables with C - 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++]

Related

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.

Difference in C main function declarations

I'm a beginner with the langage C and i'd like to know what's the difference between this:
int main(int argc, const char * argv[])
and this:
int main(int argc, char * argv[])
I think it's the same thing but i'm not sure. Could someone explain me the difference.
Thank you
int main(int argc, char * argv[]) is correct and must be accepted by the compiler.
int main(int argc, const char * argv[]) may be rejected by the compiler. If the compiler accepts it then the behaviour is implementation-defined. This means that the compiler must document which non-standard signatures of main it accepts, and document the behaviour of each one.
So, consult your compiler's documentation to see what it says about parameters of main. A reasonable expectation would be that the compiler makes this form behave the same as if you had int main(int argc, char *__argv[]) { const char **argv = (const char **)__argv; .
I guess firstly you have to know const char* c; and char *const c;
In const char* c, const means you can't change the content c points to.
In char *const c, const means you can't change the position c points to.
As you know, the value stored in char* c is an address in memory, so the first const indicates that the value that c points to isn't supposed to be changed.And the second one indicates that the value of c shouldn't be changed.
Thus, in const char * argv[], argv is an array of const char* variables.This means the content that every element in argv points to is constant.Actually, each element points to a string, and argv is an array of strings storing "arguments" that CL passes to you.It's true that you can only read the arguments but modifying them.
Of course, compiler won't block you if const is missed here.If so, you can change the content of strings in your code and I guess nothing will happen, since these arguments are for you to read. :)

Is this a valid definition for main()

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.

how to use cmd passed arguments in other function?

we declare main() as
int main(int argc, char *argv[])
and pass some argument by command line and use it
as argv[1], argv[2] in main() function definition but what if i want to use that in some other function's definition ?
one things i can do it always pass that pointer char** argv from main() to that function by argument. But is there any other way to do so?
Just pass the pointer?
int main(int argc, char** argv) {
do_something_with_params(argv);
}
void do_something_with_params(char** argv) {
// do something
}
Or if you mean passing single arguments:
int main(int argc, char** argv) {
do_something_with_argv1(argv[1]);
do_something_with_argv2(argv[2]);
}
void do_something_with_argv1(char* arg) {
// do something
}
void do_something_with_argv2(char* arg) {
// do something
}
In order to make data available to other functions, you need to pass it as a parameter, or make it available through a global (not recommended) or a static variable.
static char** args cmd_args;
static int cmd_arg_count;
int main(int argc, char** argv) {
cmd_arg_count = argc;
cmd_args = argv;
do_work();
return 0;
}
void do_work() {
if (cmd_args > 1) {
printf("'%s'\n", cmd_args[1]);
}
}
The best approach is to make a function that parses command line parameters, and stores the results in a struct that you define specifically for the purpose of representing command line arguments. You could then pass that structure around, or make it available statically or globally (again, using globals is almost universally a bad idea).
one things i can do it always pass this value from main() to that function by argument. But is there any other way to do so?
No. Passing the argc and argv to other functions is perfectly valid.
int main(int argc, char *argv[])
{
typedef struct _cmdline_arg_struct {
// all your command line arguments go here
}cmdline_arg_struct;
/* command line arguments - parsed */
cmdline_arg_struct *pc = (cmdline_arg_struct *) malloc(sizeof(cmdline_arg_struct));
if (parse_cmdline_args(&pc, argc, argv) == PARSE_FAILURE) {
usage();
return 0;
}
/* Now go through the structure and do what ever you wanted to do.. *?
}
You could have code in main() to store the values in non-local variables, and then refer to those variables from other functions.
If you really need to, store them in globals.
but what if i want to use that in some other function's definition?
You mean have another set of parameters for main? That's not possible, because main is defined in the C standard as either
int main();
or
int main(int, char*[]);
And it makes sense: The first parameter tells you the number of parameters given on the command line, the second contains the array of pointers to those parameters.
It's your responsibility to make sense of those parameters and pass them to other functions. Use string conversion functions if you need to make them numbers.

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