how to put char * argv[] to global variable - c

I am just trying to write something like that:
u64 get_env(char *argv[]);
char* g_argv[];
static char * Sample ()
{
return (char*)get_env(g_argv);
}
int main(int argc, char *argv[])
{
g_argv = argv;
Sample();
}
Getting error: 'g_argv' has an incomplete type
warning: array 'g_argv' assumed to have one element [enabled by default]
I've tried many different ways. How to write it right?

The compiler sees you declaring g_argv as an array of char pointers, but you don't specify how many.

int main(int argc, char *argv[])
Despite what it looks like, argv is not an array; arrays aren't first class objects in C and cannot be passed to functions, only their addresses can. So because argv is a parameter, it's actually a pointer to a pointer. For this reason I think it's better to tell the truth and use
int main(int argc, char** argv)
which is exactly equivalent to the above. This confusion in the language has led you to
char* g_argv[];
You're saying this is an array of pointers, without saying how big the array is, but that's not what you want; you want a pointer to the first of several pointers:
char** g_argv;
That fixes the problem you asked about, but I wonder about this declaration:
u64 get_env(char *argv[]);
Why declare it as returning u64 when the name and usage clearly indicate that it returns a char*? Actually, you should not be declaring it here at all ... it should be declared in a header file that specifies the API that includes get_env. Hopefully that header file declares it as returning a char*, and then you can remove the cast from
return (char*)get_env(g_argv);

Related

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. :)

what is different between passing in char *argv[] and declaring char *argv?

My c skills are very rusty, so I apologize if this is a dumb question, but I could not even think were to look for the answer to this simple question.
This code compiles without any warnings:
#include <ruby.h>
int run_script( int argc, char *argv[] ) {
ruby_sysinit(&argc, &argv);
}
But when I compile this code, I get the following warning:
#include <ruby.h>
int run_script( char * parameters ) {
int argc=0;
char *argv[1];
ruby_sysinit(&argc, &argv);
}
run_script_3.c: In function 'run_script':
run_script_3.c:7: warning: passing argument 2 of 'ruby_sysinit' from incompatible pointer type
it seems like i am passing the same pointer type in both cases.
The problem is that an array in formal parameter declaration is equivalent to pointer. Declaration of
int run_script( int argc, char *argv[] ) { ... }
is equivalent to
int run_script( int argc, char **argv) { ... }
because you can not send an array as parameter. You can send only a pointer and even if you put an array as actual parameter it is always converted to a pointer. Then if you put &argv you are getting address of this parameter, so it is an address in system stack where argv's value is stored.
On the other hand array in code is still an array, which is different type. In your case &argv is of type char *** inside the first version of run_script while it is of type char *(*)[1] in the second version. It looks like the same type, but it is not. In run time, there is even bigger difference, because your two invocations are sending two completely different values to ruby_sysinit.
Your second example:
int run_script( char * parameters ) {
int argc=0;
char *argv[1];
ruby_sysinit(&argc, &argv);
}
will probably cause segfault because opearator & applied on an array gives the pointer to the first element of the array. So the call ruby_sysinit(&argc, &argv); is sending the same values as ruby_sysinit(&argc, argv);, i.e. a value which points to char*, not to pointer to char* as expected by ruby_sysinit.
The signature of ruby_sysinit is as follows (correct me if I picked the wrong ruby version, I don't have the header file on my system):
void ruby_sysinit(int *argc, char ***argv);
This means that the following compiles:
extern void ruby_sysinit(int *argc, char ***argv);
int run_script(char * params) {
int argc = 0;
char **argv;
ruby_sysinit(&argc, &argv);
}
Now, when you declare char *argv[1], you tell the compiler that this is an array with one element. This is not the same as char **argv.
EDIT: you might find this question on SO and this article (as linked in the other question) useful.

C pointer and type conversion

Need some help with type conversaion with string pointers in C. I have a function that gets the the *argv from main loop to pass command-line parameters to it. Since the parameters are fixed, I am trying to give my own *argv style parameter to it, but gcc everytime gives a warning:
passing argument 2 of ‘DirectFBInit’ from incompatible pointer type
Code:
int main (int argc, char *argv[])
{
...
char *argx[2] = {"self","--dfb:no-vt"};
char *argxPtr = argx;
DFBCHECK (DirectFBInit (&fakeArgc, &argxPtr));
...
}
I should mention that the function is manipulation argv (hence argx).
Here are the definition of DirectFBInit:
DFBResult DirectFBInit(
int *argc, /* pointer to main()'s argc */
char *(*argv[]) /* pointer to main()'s argv */
);
The prog is running but I'm concerned about it.
The web-site for DirectFB probably has useful information.
Your code should probably be:
int main(int argc, char **argv)
{
...
char *argvxData[] = { "self", "--dfb:no-vt", 0 };
char **argvx = argvxData;
int argcx = 2;
DFBCHECK(DirectFBInit(&argcx, &argvx));
...
}
Note the added null pointer to match the null pointer at argv[argc] in the main() program. I've not read the manual to ensure that's required, but consistency is good. When I checked the first edition of my answer, it did not compile without warnings — in fact, it got your warning; I've fixed that with the argvxData array and argvx double pointer. The [] in the prototype is mostly a red-herring, but avoids accusations of being a three-star programmer. It is equivalent to char ***argv.
Or you could pass the arguments to main:
DFBCHECK(DirectFBInit(&argc, &argv));
If we call char * "string" then that simplifies it a bit. The function expects a pointer to an array of strings. You are passing in a string, and an incorrectly-initialized string at that (argx has type char*[] but you are assigning it to a variable of type char*).
&argxPtr should actually be &argx (an expression of type char*(*[]) as expected by the function), and you don't need argxPtr at all.
Something like this?
int myargc = 2;
const char *myargv[] = { "self", "--dfb:no-vt" };
DirectFBInit(&myargc, &myargv);
A simple way to verify is to compile with -g and run gdb. Once in gdb, run the program, and type ptype and you will see the difference. I have replaced the func name with foo()
foo(int *argc, char *(*argv[]))
{
}
int
main (int argc, char *argv[])
{
char *argx[2] = {"self","--dfb:no-vt"};
char *argxPtr = argx;
foo (&argc, &argxPtr);
}
(gdb) ptype foo
type = int (int *, char ***)
(gdb) ptype main
type = int (int, char **)
Hence the warning. Hope this helps.

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.

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);
}

Resources