what is the difference between these two function pointer declarations? - c

int *(*const fun[])(int argc, char **argv)
and
const int *(* fun[])(int argc, char **argv).
Is the first one the array of const function pointers returning integer pointer ?

The first one is an array of read-only pointers (i.e. you can't change fun[i]) to a function receiving an int and a char **, and returning a pointer to int.
The second is pretty similar, except that you can change fun[i], but the function it points to returns a pointer to a read-only integer.
So, in short:
/* First declaration
int *(*const fun[])(int argc, char **argv)
*/
int arg1;
char **arg2;
int *example = (*fun[i])(arg1, arg2);
*example = 14; /* OK */
example = &arg1; /* OK */
fun[i] = anoter_function; /* INVALID - fun[] is an array of read-only pointers */
/* Second declaration
const int *(* fun[])(int argc, char **argv)
*/
const int *example2 = (*fun[i])(arg1, arg2);
fun[i] = another_function; /* OK */
*example2 = 14; /* INVALID - fun[i] returns pointer to read-only value. */
example2 = &arg1; /* OK */

Related

What is the meaning of changing char pointer to int pointer

I have the following code from previous exam in c:
int main(int argc, char **argv) {
char s[] = "123";
int* a = (int*) s;
printf(("%x"),*a);
return 0;
}
The output is: 333231
My question is why? how does changing the pointer effect it?
You don't have to declare a separate variable. This would do:
printf(("%x"),(int*)s);
The pointer type dictates how the pointee is interpreted when the pointer is dereferenced.

In C, how to set an unsigned char array from argv

In the code below, I would like to have the value of myvar be provided by a program argument.
#include <stdio.h>
int main(int argc, const char **argv)
{
const unsigned char myvar[] = "myvalue";
return 0;
}
How would I get myvar to contain the value of the string from argv[1]?
If you are only reading, then you can simply copy the address of argv[1] like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char **argv) {
const unsigned char *myvar = NULL;
// Be sure to check argc first
if (argc < 2) {
fprintf(stderr, "Not enough arguments.\n");
return EXIT_FAILURE;
}
myvar = (const unsigned char *)argv[1];
printf("myvar = %s\n", myvar);
}
If you want to change myvar then you should copy the string with strncpy or alike.
An array cannot be initialized by a pointer or by another array. You can only initialize it with an initializer list or (in the char of a char array) a string constant.
What you can do it copy the contents of another string with strcpy. And since you'll be using this array as a parameter to an encryption function, it will probably need to be a fixed size.
char myvar[8] = { 0 }; // initialize all values to 0
strncpy(myvar, argv[1], 8); // copy the first 8 bytes

Trouble Copying Char* to Char* in C

I have the following program I am trying to run but surely, due to my lack of good knowledge, my program crashes runtime:
#include <stdio.h>
#include "ptref.h"
mystruct_t *FRSt = NULL;
int main(int argc, char* argv[])
{
char ct[2] = {0, 1, '\0'};
char dd[2] = {0, 1, '\0'};
populate_contents(FRSt, 2, "FRES", ct, dd);
return 0;
}
HEADER
/*
* ptref.h
*
*/
#ifndef PTREF_H_
#define PTREF_H_
typedef struct mystruct
{
char* ct[2]; //
char* dd[2]; // = "0\0";
char* name[]; // = "1\0";
} mystruct_t;
extern mystruct_t p;
void populate_contents(mystruct_t* mystruct_var, int arrSize, char* name[], char* dd[], char* ct[])
{
/* Initialise arrays */
int i;
i = 0;
strncpy(mystruct_var->name, name, sizeof(name));
for (i = 0; i < arrSize; i++)
{
mystruct_var->dd[i] = dd[i];
mystruct_var->ct[i] = ct[i];
}
return;
}
#endif /* PTREF_H_ */
Because I am going to implement this in a real-time computer, I am not sure if using malloc will cause me any trouble. However, I have got a feeling that because I have not used malloc for my mystruct_var pointer, I am having trouble, or may be it is my moronic code. In any way, further education and advise will be highly appreciated.
P.S. I have looked into the other relevant post but my problem is quite different. So, I posed a new question.
Firstly, in main() char ct[2] = {0, 1, '\0'}; this particular array initialization is incorrect as you have defined array size as 2 and initializing 3 array elements.
In function populate_contents(FRSt, 2, "FRES", ct, dd);, the third argument is a character string which corresponding called function argument should be a char array as char name[] or char pointer as char *name. It should not be as you defined name as array of pointers char *name[]. Same thing goes for arguments passed ct & dd, they should be just char pointers in the callee function as there type is char *.
Also your structure mystruct_t declared is incorrect by the way looking at your usage of member elements.
As said by Grijesh, sizeof(name) is what you don't want as name is a pointer which could be 4 or 8 Bytes, so make use of strlen() to get the length of the string you received.

Mysterious C function calling

I have this code:
int indexOf(const char *array[], char *e)
{
printf("inside: %d\n",(int)sizeof(array));
/* ... */
}
int main(int argc, char *argv[])
{
const char *a[] = {";", ",", ":", "==", ":="};
char *b = "==";
printf("outside: %d\n",(int)sizeof(a));
int d = indexOf(a,b);
/* ... */
}
And this is the output:
outside: 40
inside: 8
Why output is not the same? Any help, please?
The array decays into a pointer to it's first element when passed to a function. The sizeof from the function yields the size of the pointer on your implementation. You could have declared it:
int indexOf(const char **array, char *e)
You will probably want to pass the length as a separate parameter.
EDIT
What I'm trying is to avoid to pass the size as a parameter.
In that case you could mark the end of the array with a NULL
const char *a[] = {";", ",", ":", "==", ":=", NULL};
That way in the function you will know where it ends.

Passing char * vs char ** as parameters to a function in C

I've read several discussions of passing char * in C.
stackoverflow: passing-an-array-of-strings-as-parameter-to-a-function-in-c
stackoverflow: how-does-an-array-of-pointers-to-pointers-work
stackoverflow: whats-your-favorite-programmer-ignorance-pet-peeve
drexel.edu: Character arrays
Many of them include discussions of arrays, but I want to stay away from that.
I'm writing a sample program to teach myself about the passing of char * and char ** in C. This is an exercise in passing char *, without using (pointers to) arrays. Also no concerns for execution efficiency. :-)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void get_args_works(int, char **, char **);
void get_args_broken(int, char **, char *);
char *get_string(int, char **);
int main(int argc, char **argv)
{
char *string_works;
char *string_broken;
get_args_works(argc, argv, &string_works);
get_args_broken(argc, argv, string_broken);
printf("in main string_works (%p) = %s\n",string_works,string_works);
free(string_works);
printf("in main string_broken (%p) = %s\n",string_broken,string_broken);
free(string_broken);
}
void get_args_works(int argc, char **argv, char **string)
{
*string = get_string(argc, argv);
printf("in get_args_works %p string %s\n",*string,*string);
}
void get_args_broken(int argc, char **argv, char *string)
{
string = get_string(argc, argv);
printf("in get_args_broken %p string %s\n",string,string);
}
char * get_string(int argc, char **argv)
{
int i;
char *string;
string = malloc(40);
// placeholder in case -s switch not found below
strcpy(string,"-s switch not found below");
for(i = 0; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 's':
// release above malloc(40) for "-s switch not found below"
free(string);
// make room for storing variable
string = malloc(strlen(argv[++i]) + 1);
// the argv just after -s
strcpy (string,argv[i]);
break;
}
}
}
return string;
}
You can also view the same code on github
The above code is somewhat self documenting. main() declares two char * variables, and passes them as parameters to their respective get_args() functions.
Each get_args() function calls char * get_string(int, char **), using the exact same call (but different way to collect the return value).
get_string() works fine; it does a malloc() and returns the pointer back to the calling function. That code works, and each get_args() function receives the return value as I expect.
But then, when the get_args() functions return to main(), why does the dereferenced pointer value get back to main (from get_args_works(), but not the pointer's value (from get_args_broken())?
(i.e. I can see that if I dereference the pointer (&string_works) when sending as a parameter, it works. But why? Isn't char * string_broken already a pointer? Why does it need the "extra" dereference when sending as a parameter?)
I'm hoping for a winning answer that explains how you (yes, you) conceptualize sending char * as a parameter vs receiving it as the function's return value.
int get_args_broken(int argc, char **argv, char *string)
{
string = get_string(argc, argv);
printf("in get_args_broken %p string %s\n",string,string);
}
You're only modifying the string local (automatic) variable. That's not visible to the caller in any way. Note that this means you're freeing a wild pointer in main.
It's wrong for the same reason:
int get_sum(int sum, int a, int b)
{
sum = a + b;
}
is; the parameter is copied by value. Also, you're not returning an int (as you declared you would).
int get_args_works(int argc, char **argv, char **string)
{
*string = get_string(argc, argv);
printf("in get_args_works %p string %s\n",*string,*string);
}
is correct (except the missing return). You're not modifying string, which would be pointless. You're modifying the object at the location in string, which in this case is a char *.
EDIT: You would need to triple * the argv if there was a function calling main, and you wanted to set that function's variable to a different char **. E.G.
void trip_main(int *argc, char ***argv)
{
*argc = 10;
*argv = malloc(*argc * sizeof(char *));
}
void caller()
{
char **argv;
int argc;
trip_main(&argc, &argv);
}
One of the needs to use Pointer to a pointer (here get_args_works()) is to modify (or return) more than on variable from a function, as in C it's not possible to return more than one variable.
get_args_works() works 'coz, you are passing pointer to a pointer & a reference to it is there in your main().
But in get_args_broken() you are passing just a pointer. Nothing wrong here, now you do malloc() & return back the memory allocated string to get_args_broken(), still nothing wrong here. But now, this mem allocated string is local & main() does not have a reference to this var. So when you dereference char *string_broken; in main() it might cause undefined behavior.
Hope this's clear.

Resources