assign pointer from argv in function - c

I am trying to assign a pointer correctly from the programs **argv. When I assign data in the main function it works fine, but when I attempt to place that logic into a separate function it does not.
What am I doing wrong here?
void parse_args(char *argv[ ], unsigned char *data, *data_len, *nprocs){
data = (unsigned char *)argv[1];
*data_len = strlen(argv[1]);
*nprocs = atoi(argv[2]);
}
int main(int argc, char **argv) {
unsigned char *data;
int data_len;
int nprocs;
// this doesnt work (for data)
parse_args(argv, data, &data_len, &nprocs)
// this works (for data)
data = (unsigned char *)argv[1];
}

This line
data = (unsigned char *)argv[1];
modifies a local copy of main's local data, because all parameters, including pointers, are passed by value. If you would like to modify data inside main, pass it by pointer (i.e. you need a pointer to pointer now):
void parse_args(char *argv[ ], unsigned char **data_ptr, int *nprocs) {
...
*(data_ptr) = (unsigned char *)argv[1];
...
}

your function needs to be passed a char * [] (which is equivalent to a char** in an argument specification). You shouldn't specify the type when calling a function, that should have given you a compiler error (char * is not to be used here!)
// this doesnt work (for data)
parse_args(char *argv, data, &data_len)
must be replaced by
parse_args(argv, data, &data_len)
So, next, you pass a pointer data , but you pass that pointer by value, i.e. your parse_args gets a nice copy of that pointer (which, technically, is just an address stored in a variable), and then you modify that copy. You might want to pass it like data_len:
void parse_args(char *argv[ ], unsigned char **data, *data_len, *nprocs){
..
parse_args(argv, &data, &data_len, &nprocs)
All in all, this doesn't seem to be a great attempt at argument parsing. There's lots of libraries out there to do that for you, and if you want to stay old-school, I'd recommend using gengetopt, which generates all the parsing code you need and has nice documentation.

Related

How to pass a struct array to a function

I want to pass a struct array into a function, however, there's something wrong with how I'm passing it and I cant figure out what. I'll include the relevant code.
The Struct:
typedef struct fitbit
{
char patient[10];
} FitbitData;
Main.c:
FitbitData* data = (FitbitData*)malloc(sizeof(data) * 1450);
count = storeToksInArray(line, count, data);
function:
int storeToksInArray(char line[], int count, FitbitData* data[])
{
strcpy(data[count]->patient, strtok(line, ",")); //name
puts(data[count]->patient); }
I've already tested my code and there aren't any problems with line or count. The array works fine in my main file, but once I pass it into the function I can't get it to store the data correctly. The strcpy and puts functions work fine in main as well, so I'm 90% sure it's how I'm passing the array into the function and then using it in the function. I can also use the strtok and puts functions fine by themselves in the function, but once I try storing the token in the array, it doesn't work.
Edit: I figured it out! I removed the brackets after FitbitData data[] to get FitbitData data and then change -> to .**
int storeToksInArray(char line[], int count, FitbitData* data[])
The expression FitbitData* data[] means data is an array of pointers to FitbitData. You seem to be wanting instead a pointer to an array of FitbitData. But an array type is effectively a pointer, so you don't need to pass a pointer to it. Consider changing your function declaration to:
int storeToksInArray(char line[], int count, FitbitData data[])
It appears that data is a FitbitData pointer, and yet your function is expecting an array of FitbitData pointers. Perhaps what you want is either:
int storeToksInArray(char line[], int count, FitbitData* data)
or
int storeToksInArray(char line[], int count, FitbitData data[])
Both are equivalent in this context, it's a question of which you prefer or which seems clearer to you. Personally, I prefer the first one.

Interface with variable argument list function, by using function pointers

I am trying to use an interface of another program, where I have to use the following method:
void iterate_over_entries(Table* table, Func_ptr f, ... )
so the function is designed to call on each table entry the function f() which is user-defined.
The function pointer is defined as:
typedef size_t (*Func_ptr) (char* example, va_list args);
So that means that I have to write a function which is of type Func_ptr in order to manipulate the entries of the table?
So lets say for example I want to whatever - set all strings which have a length below a given one to be "a". Is it then, that I have to put the length into this va_list?
size_t my_method(char* example, va_list args) {
int length = va_arg(args, int);
if (strlen(example) < length) strncpy(example, "a\0", 2);
return 1;
}
So If I did everything so far correct, I only need to call the function, but I have no idea how to do that.. Lets say I want that the command line input sets me the length I allow...
int main(int argc, char** argv){
Table* table; //this is set somehow..
int length = atoi(argv[1]);
size_t (*method)(char* example, va_list list);
method = &my_method;
}
So how do I now tell the program to call iterate_over_entries with with my_method, where the length to my input... :S
Just call it:
int main(int argc, char** argv){
Table* table; //this is set somehow..
int length = atoi(argv[1]);
Func_ptr method;
method = &my_method;
iterate_over_entries(table, method, length);
}
There's no need to assign my_method to another variable, you can just pass it directly.
iterate_over_entries(table, my_method, length);

C: Illegal conversion between pointer types: pointer to const unsigned char -> pointer to unsigned char

The following code is producing a warning:
const char * mystr = "\r\nHello";
void send_str(char * str);
void main(void){
send_str(mystr);
}
void send_str(char * str){
// send it
}
The error is:
Warning [359] C:\main.c; 5.15 illegal conversion between pointer types
pointer to const unsigned char -> pointer to unsigned char
How can I change the code to compile without warnings? The send_str() function also needs to be able to accept non-const strings.
(I am compiling for the PIC16F77 with the Hi-Tech-C compiler)
Thanks
You need to add a cast, since you're passing constant data to a function that says "I might change this":
send_str((char *) mystr); /* cast away the const */
Of course, if the function does decide to change the data that is in reality supposed to be constant (such as a string literal), you will get undefined behavior.
Perhaps I mis-understood you, though. If send_str() never needs to change its input, but might get called with data that is non-constant in the caller's context, then you should just make the argument const since that just say "I won't change this":
void send_str(const char *str);
This can safely be called with both constant and non-constant data:
char modifiable[32] = "hello";
const char *constant = "world";
send_str(modifiable); /* no warning */
send_str(constant); /* no warning */
change the following lines
void send_str(char * str){
// send it
}
TO
void send_str(const char * str){
// send it
}
your compiler is saying that the const char pointer your sending is being converted to char pointer. changing its value in the function send_str may lead to undefined behaviour.(Most of the cases calling and called function wont be written by the same person , someone else may use your code and call it looking at the prototype which is not right.)

Send number / character / string to void* function

Is there a way to do something like this : ?
void set(void* data, void *value, t_flags type)
{
if (type & INT)
*(int*)data = *(int*)value;
if (type & UINT)
(...)
}
int i;
set(&i, 42, INT);
My set function works but I don't know how to call it with number, char '', or string "".
Edit : I've forgot the last argument, but the problem come from the 42 argument.
A few things. First, since you're using a void* (which is appropriate) for value, you need to pass a void* as your second argument, instead of a constant. This will work to copy one variable to the next, but there are more efficient ways.
Second, note that for passing a string, you need to pass a pointer to a char pointer, and the char* will get set by the function. (It's up to you whether it's a "soft copy" or "hard copy" - i.e. whether the pointer points to the same place in memory or to another copy of the same string. You said you had set implemented, so I'm guessing you already have it the way you want.
You haven't included your t_flags enum, so I guessed appropriate values.
char c = 'c';
char* str = "str";
int i = 42;
char c2;
char* str2;
char i2;
set(&c2, &c, CHAR); /* presumably you have a CHAR flag? */
set(&str2, &str, CHARPTR); /* presumably you have a CHARPTR flag? */
set(&i2, &i, INT);
The bigger question for me is why you would want to do this, especially since in your flag you already need to know the type. It's much cleaner (and has much better type checking) to simply do:
c2 = c;
str2 = str;
i2 = i;
I'm assuming this is just for learning about functions, or it's massively simplified for a complex issue. Either way, that's how you do it.
Maybe you want this:
void set(void* data, void *value, t_flags type)
{
if (type & INT)
*(int*)data = *(int*)value;
if (type & UINT)
*(unsigned int*)data = *(unsigned int*)value;
if (type & STRING)
strcpy((char*)data, (char*)value);
...
}
int i;
char string[100] ;
set(&i, 42, 1<<INT);
set(string, "Hello world", 1<<STRING) ;
But it's weird anyway.

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.

Resources