I'm confused about these errors. The str1 is a string that is being passed but I get the a warning at the compare and and error at the if statement
int stringcmp(void* str1, void* str2) {
int a = strlen(str1);
int b = strlen(str2);
int x;
if ( a < b ) {
x = a;
} else {
x = b;
}
int c = 0;
while ( c < x ) {
if (str1[c] < str2[c]) { //errors happen here
return 0;
}
if (str1[c] > str2[c]) {
return 1;
}
c++;
}
if ( a == x ) {
return 0;
}
return 1;
}
Your function receives void* arguments, so in the line you pointed you are dereferencing pointers to void and that is why you get the warnings. I am not sure why you are receiving the value not ignore as it ought to be because that means that you are assigning the value of a function that returns void, and that is not the case of strlen (which is the only one you are calling).
And you should also receive an error in the calls to strlen when passing to it a void* parameter.
So you have to change your function's signature to
int stringcmp(const char* str1, const char* str2);
to suppress the warnings and be able to call strlen on the strings.
Dereferencing void * makes no sense, ever. In C, void means "no type"/"nothing", if you have void *p;, what is *p supposed to be?
In C, void * is used as a generic pointer type, "pointer to anything". To use p above, you must cast it to the type of the object it is pointing at (passed in some other way, unbeknownst to the compiler). E.g.:
int i;
void *p = (void *) &i;
...
int j = *(int *)p;
You know what p points to, the compiler doesn't.
The type void * is often used to pass around opaque data, or to write generic functions (like qsort, it gets an array of unspecified elements and a function that compares them).
That said, as a (misguided) extension GCC allows pointer arithmetic on void *, so that p + 1 is like ((char *)p + 1), it points at the next char position.
Your error arises from the fact that you are attempting to use the array notation str1[c] on a void-pointer. To understand why this is wrong we need to look at what the array notation in C actually means.
Let us assume that we define char* str1. Here we have said that str1 is an address to some place in memory where there is a char.
To get the data that is stored on the address which str1 is referring to we can use *str1.
This is equivalent to saying: "Go to the address that str1 is holding and give me what is stored on that address".
When we use the array notation we can use str1[0], this will be a value fetched from a place in memory where there is an element of the same type that str1 was defined as. It is the same thing as saying *str1 (go to the address that str1 is pointing to and give me the value that is stored there).
An array is just a bunch of data stored in a sequence in memory and strings are just arrays of characters of exactly 1 byte in size stored immediately after one another.
When we say str1[1] we are telling the compiler to move by the size of the type that str1 was defined to be pointing at, in this case 1 byte(char), and then get us whatever is stored at that location. In the case of strings, this should be another char.
Now when we have defined str1 as void*, how would the compiler know how how much it should move in memory to get the next element in the array? Since void has no size it is impossible.
Hopefully you now understand what you need to change in this line to get rid of your errors
int stringcmp(void* str1, void* str2)
I want to copy the bits from one void * to another void *.
How can I do it?
I tried this:
static void* copyBlock(void* ptr) {
if (!ptr) {
return NULL;
}
int sizeOfBlock=*(int*)ptr+13;
void* copy = malloc(sizeOfBlock);
if (!copy) {
return NULL;
}
for(int i=0;i<sizeOfBlock;i++){
*(copy+i)=*(ptr+i);
}
return copy;
}
but I get: invalid use of void expression
You cannot dereference, perform pointer arithmetic, indexing a void pointer because it has no base type or object size. You must therefore cast the void pointer to the a pointer to the type of the data units you are copying so that the compiler will know the size of the data to copy.
All that said, you'd be better off using:
memcpy( copy, prt, sizeOfBlock ) ;
This design (storing block size inside of a block without any struct) seems dangerous to me, but I still know the answer.
*(copy+i)=*(ptr+i);
Here you get the error, because you can't dereference a void pointer. You need to cast it to pointer to something before. Like this:
((char *)copy)[i] = ((char *)ptr)[i];
You should use the memcpy function:
memcpy(copy, ptr, sizeOfBlock);
Depending on the compiler settings (you may be compiling as C++ and not as C), you may need to cast the pointers to a char pointer:
memcpy((char *) copy, (const char *) ptr, sizeOfBlock);
Note: The parameter of the function should be const char *ptr, to make sure you don't change the contents of ptr by mistake.
I have a question for the exact meaning of a pointers phrase.
I have the following method:
myFunc(const void * p)
{
...
}
And it is being called by:
myStruct *st;
...
myFunc((char **)&st->arr);
I have experience with pointers, but in this case I still get lost with all these pointers and casting..
Can I get please an accurate explanation about how this case works?
Thanks
This seams to be bad quality code! Maybe not dangerous, as const appears in prototype.
myFunc(const void * p) accepts a pointer to anything and const should mean it won't touch it.
Now, st is a pointer to myStruct, so st->arr is the value of arr member and &st->arr is memory address of arr member. Assuming arr is an array, st->arr value is already a pointer.
So, (char**) is possibly the correct type of &st->arr, it is a pointer to a character array. And if it is the correct type, there is no need to cast!
You cast when you need to tell the compiler to handle your data as another data. It would make sense, in this case myFunc((const void *)&st->arr);
Anyway, without further information on myFunc, I belive that true programmer intention was myFunc((const void *) st->arr);
the address of st->arr is being converted to a char** (i.e. the address where to find a pointer to a char). myFunc accepts pretty much anything (void*) and you must be careful to pass it something it knows how to handle.
Internally, myFunc can do something like this:
struct myStruct{
char* arr;
};
void myFunc(const void* ptr){
char** cPtr = (char**) ptr;
(*cPtr)[1] = ...;
}
int main()
{
struct myStruct s;
...
myFunc((char **)&s.arr);
...
}
However, you should notice that this is extremely bad (as in "dangerouse") code.
You are calling the method myFunc with a double pointer char ** and the same you are catching with the const void *ptr . In C a void pointer can hold the other pointer types like(char */float */int */...), later on we can typecast them when we are using.
So here a void pointer can able to hold a double character pointer and you can typecast the void pointer to a double character pointer later on like
char **tempPtr = (char **)p;
Here const qualifier makes the pointer p as a constant data pointer, which means inside the function it wont change the data it is pointing to.
Alright here's the code:
//in another file
void **ptr; ptr = kmalloc(sizeof(void *) * 2);
*(ptr+0) = tf; //type trapframe *
*(ptr+1) = as; //type addrspace *
func(*ptr);
And here is that function:
void func(void *ptr) {
struct trapframe *parentTF = ptr[0];
struct addrspace *newAS = ptr[1];
//now I wanna do stuff with parentTF and newAS
}
And the error I get is:
warning: dereferencing `void *' pointer
Thanks for any help.
If I'm correctly understanding what you're trying to do, it seems like you need to change this:
void func(void *ptr) {
to this:
void func(void **ptr) {
and this:
func(*ptr);
to this:
func(ptr);
Note that *(ptr+0) and ptr[0] are synonymous, as are *(ptr+1) and ptr[1].
You're declaring ptr as a void ** but using it as a void *. They're different.
First cast the void pointer array to an array of the pointer type you want. i.e, you need to do such changes:
((trapframe **)ptr)[0] = tf; //type trapframe *
and another cast like this:
struct trapframe *parentTF = ((trapfname**)ptr)[0];
And what did you expect? The function's parameter ptr is a pointer to "something" (i.e. void). You dereference that pointer with ptr[0] and ptr[1], trying to extract "somethings". But the compiler doesn't know the type or size of "something".
What you probably want is this:
func(ptr);
and this:
void func(void** ptr)
{
...
}
In func, where ptr is declared as a void*, ptr[0] is the same as *ptr and ptr[1] is the same as *(ptr + 1). You're attempting to dereference a void pointer, as your compiler's telling you.
If you want to pass an array of void pointers to func, then you would make the following changes:
Change the signature of func to:
void func(void **ptr)
Change func(*ptr); to simply func(ptr); to pass the dynamically allocated array ptr to the function.
I also don't understand why you'd split the declaration and initialisation of ptr in the top snippet into two statements. Just have:
void **ptr = kmalloc(sizeof(void *) * 2);
or even:
void **ptr = kmalloc(sizeof(*ptr) * 2);
Your code screams wrongness because of the inconsistencies between the two files. In one, you access ptr[0] and ptr[1], while in the other you access *(ptr + 0) and *(ptr + 1) ... that happens not to be a source of error here because the two syntaxes mean the same thing, but using two different forms is bad style, reads badly, and is error prone. But then, in one file you declare void **ptr but in the other file you declare void *ptr -- that can't possibly be be right, since the two ptrs have the same semantics (they each point to an array of two elements, a tf and an as). In one file you have a function that takes a parameter called ptr, but in the other file you pass the contents of a variable named ptr ... again, since the two ptrs have the same semantics, this inconsistency must be wrong, and clearly it's the dereference that is wrong. Remove that and you're passing a void**, so that's what the parameter of func should be.
Code consistently and a whole class of errors will disappear from your code. You can code for 3 years or for 30 years, but it doesn't matter if you don't learn such fundamentals.
How do I understand following complicated declarations?
char (*(*f())[])();
char (*(*X[3])())[5];
void (*f)(int,void (*)());
char far *far *ptr;
typedef void (*pfun)(int,float);
int **(*f)(int**,int**(*)(int **,int **));
As others have pointed out, cdecl is the right tool for the job.
If you want to understand that kind of declaration without help from cdecl, try reading from the inside out and right to left
Taking one random example from your list char (*(*X[3])())[5];
Start at X, which is the identifier being declared/defined (and the innermost identifier):
char (*(*X[3])())[5];
^
X is
X[3]
^^^
X is an array of 3
(*X[3])
^ /* the parenthesis group the sub-expression */
X is an array of 3 pointers to
(*X[3])()
^^
X is an array of 3 pointers to function accepting an unspecified (but fixed) number of arguments
(*(*X[3])())
^ /* more grouping parenthesis */
X is an array of 3 pointers to function accepting an unspecified (but fixed) number of arguments and returning a pointer
(*(*X[3])())[5]
^^^
X is an array of 3 pointers to function accepting an unspecified (but fixed) number of arguments and returning a pointer to an array of 5
char (*(*X[3])())[5];
^^^^ ^
X is an array of 3 pointers to function accepting an unspecified (but fixed) number of arguments and returning a pointer to an array of 5 char.
Read it out from the inside, similar to how you would solve equations such as {3+5*[2+3*(x+6*2)]}=0 - you'd start by solving what's inside () then [] and finally {}:
char (*(*x())[])()
^
This means that x is something.
char (*(*x())[])()
^^
x is a function.
char (*(*x())[])()
^
x returns a pointer to something.
char (*(*x())[])()
^ ^^^
x returns a pointer to an array.
char (*(*x())[])()
^
x returns a pointer to an array of pointers.
char (*(*x())[])()
^ ^^^
x returns a pointer to an array of pointers to functions
char (*(*x())[])()
^^^^
Meaning the array pointer returned by x points to an array of function pointers that point to functions that return a char.
But yeah, use cdecl. I used it myself to check my answer :).
If this is still confusing you (and it probably should), try to do the same thing on a piece of paper or in your favorite text editor. There's no way of knowing what it means just by looking at it.
Sounds like a job for the cdecl tool:
cdecl> explain char (*(*f())[])();
declare f as function returning pointer to array of pointer to function returning char
I looked around for an official homepage for the tool, but couldn't find one that seemed genuine. In Linux, you can typically expect your distribution of choice to include the tool, so I just installed it in order to generate the above sample.
You should be using cdecl tool. It should be available on most Linux distributions.
e.g. for this function, it will return you:
char (*(*f())[])(); - declare f as function returning pointer to array of pointer to function returning char
void (*f)(int,void (*)()); - prototype of function pointer f. f is a function that takes two parameters, the first one is int, and the second one is a function pointer for a function which returns void.
char far *far *ptr; - ptr is a far pointer to a far pointer (which points to some char/byte).
char (*(*X[3])())[5]; - X is an array of 3 pointers to function accepting an undeterminate number of arguments and returning a pointer to an array of 5 char.
typedef void (*pfun)(int,float); - declaring function pointer pfun. pfun is a fuctnion that takes two parameters, first one is int, second one is of float type. the function does not have a return value;
e.g.
void f1(int a, float b)
{ //do something with these numbers
};
Btw, complicated declarations as the last one are not seen often. Here is an example I just made up for this purpose.
int **(*f)(int**,int**(*)(int **,int **));
typedef int**(*fptr)(int **,int **);
int** f0(int **a0, int **a1)
{
printf("Complicated declarations and meaningless example!\n");
return a0;
}
int ** f1(int ** a2, fptr afptr)
{
return afptr(a2, 0);
}
int main()
{
int a3 = 5;
int * pa3 = &a3;
f = f1;
f(&pa3, f0);
return 0;
}
It appears that your actual question is this:
What's the use case for a pointer to a pointer?
A pointer to a pointer tends to show up when you have an array of some type T, and T itself is a pointer to something else. For example,
What's a string in C? Typically, it's a char *.
Would you like an array of strings from time to time? Sure.
How would you declare one? char *x[10]: x is an array of 10 pointers to char, aka 10 strings.
At this point, you might be wondering where char ** comes in. It enters the picture from the very close relationship between pointers arithmetic and arrays in C. An array name, x is (almost) always converted to a pointer to it's first element.
What's the first element? A char *.
What's a pointer to the first element? A char **.
In C, array E1[E2] is defined to be equivalent to *(E1 + E2). Usually, E1 is the array name, let's say x, which automatically converted to a char **, and E2 is some index, say 3. (This rule also explains why 3[x] and x[3] are the same thing.)
Pointers to pointers also show up when you want a dynamically allocated array of some type T, which is itself a pointer. To start with, let's pretend we don't know what type T is.
If we want a dynamically allocated vector of T's, what type do we need? T *vec.
Why? Because we can perform pointer arithmetic in C, any T * can serve as the base of a contiguous sequence of T's in memory.
How do we allocate this vector, say of n elements? vec = malloc(n * sizeof(T));
This story is true for absolutely any type T, and so it's true for char *.
What's the type of vec if T is char *? char **vec.
Pointers to pointers also show up when you have a function that needs to modify an argument of type T, itself a pointer.
Look at the declaration for strtol: long strtol(char *s, char **endp, int b).
What's this all about? strtol converts a string from base b to an integer. It wants to tell you how far into the string it got. It could perhaps return a struct containing both a long and a char *, but that's not how it's declared.
Instead, it returns its second result by passing in the address of a string which it modifies before returning.
What's a string again? Oh yeah, char *.
So what's an address of a string? char **.
If you wander down this path long enough, you can also run into T *** types, although you can almost always restructure the code to avoid them.
Finally, pointers to pointers appear in certain tricky implementations of linked lists. Consider the standard declaration of a doubly-linked list in C.
struct node {
struct node *next;
struct node *prev;
/* ... */
} *head;
This works fine, although I won't reproduce the insertion/deletion functions here, but it has a little problem. Any node can be removed from the list (or have a new node inserted before it) without reference the head of the list. Well, not quite any node. This isn't true of the first element of the list, where prev will be null. This can be moderately annoying in some kinds of C code where you work more with the nodes themselves than with the list as a concept. This is a reasonably common occurrence in low-level systems code.
What if we rewrite node like this:
struct node {
struct node *next;
struct node **prevp;
/* ... */
} *head;
In each node, prevp points not at the previous node, but at the previous nodes's next pointer. What about the first node? It's prevp points at head. If you draw out a list like this (and you have to draw it out to understand how this works) you'll see that you can remove the first element or insert a new node before the first element without explicitly referencing head by name.
x: function returning pointer to
array[] of pointer to function
returning char" - huh?
You have a function
That function returns a pointer.
That pointer points to an array.
That array is an array of function pointers(or pointers to functions)
Those functions returns char*.
what's the use case for a pointer to a pointer?
One is to facilitate return values through arguments.
Lets say you have
int function(int *p)
*p = 123;
return 0; //success !
}
You call it like
int x;
function(&x);
As you can see, for function to be able to modify our x we have to pass it a pointer to our x.
What if x was not an int, but a char * ? Well, its still the same, we have to pass a pointer to that. A pointer to a pointer:
int function(char **p)
*p = "Hello";
return 0; //success !
}
You call it like
char *x;
function(&x);
Remo.D's answer for reading functions is a good suggestion. Here are some answers to the others.
One use-case for a pointer to a pointer is when you wish to pass it to a function that will modify the pointer. For example:
void foo(char **str, int len)
{
*str = malloc(len);
}
Also, this could be an array of strings:
void bar(char **strarray, int num)
{
int i;
for (i = 0; i < num; i++)
printf("%s\n", strarray[i]);
}
Typically, one shouldn't use declarations this complicated, although sometimes you do need types that are pretty complicated for things like function pointers. In those cases, it's much more readable to use typedefs for intermediate types; for example:
typedef void foofun(char**, int);
foofun *foofunptr;
Or, for your first example of "function returning pointer to array[] of pointer to function returning char", you might do:
typedef char fun_returning_char();
typedef fun_returning_char *ptr_to_fun;
typedef ptr_to_fun array_of_ptrs_to_fun[];
typedef array_of_ptrs_to_fun *ptr_to_array;
ptr_to_array myfun() { /*...*/ }
In practice, if you're writing anything sane, many of those things will have meaningful names of their own; for instance, these might be functions returning names (of some sort), so fun_returning_char could be name_generator_type, and array_of_ptrs_to_fun could be name_generator_list. So you could collapse it a couple of lines, and only define those two typedefs -- which are probably going to be useful elsewhere in any case.
char far *far *ptr;
This is an obsolete Microsoft form, dating back to MS-DOS and very early Windows days. The SHORT version is that this is a far pointer to a far pointer to a char, where a far pointer can point anywhere in memory, as opposed to a near pointer which could only point anywhere in 64K data segment. You really don't want to know the details about Microsoft memory models for working around the utterly brain-dead Intel 80x86 segmented memory architecture.
typedef void (*pfun)(int,float);
This declares pfun as a typedef for a pointer to a procedure that takes an int and a float.
You would normally use this in a function declaration or a prototype, viz.
float foo_meister(pfun rabbitfun)
{
rabbitfun(69, 2.47);
}
We have to evaluate all pointer declaration statements from left to right, starting from where the pointer name or declaration name is declared on the statement.
While evaluating the declaration, we have to start from the innermost parenthesis.
Start with the pointer name or function name followed by the rightmost characters in the parenthersis and then follwed by the leftmost characters.
Example:
char (*(*f())[])();
^
char (*(*f())[])();
^^^
In here f is a function name, so we have to start from that.
f()
char (*(*f())[])();
^
Here there are no declarations on the righthand side of the current
parenthesis, we do have to move to the lefthand side and take *:
char (*(*f())[])();
^
f() *
We have completed the inner parenthesis characters, and now we have to go back to one level behind this:
char (*(*f())[])();
------
Now take [], because this is on the right side of the current parenthesis.
char (*(*f())[])();
^^
f() * []
Now take the * because there is no character on the right side.
char (*(*f())[])();
^
char (*(*f())[])();
^
f() * [] *
char (*(*f())[])();
Next evaluate the outer open and close parenthesis, it's indicating a function.
f() * [] * ()
char (*(*f())[])();
Now we can add data type at the end of the statement.
f() * [] * () char.
char (*(*f())[])();
Final answer:
f() * [] * () char.
f is a function returning pointer to array[] of pointers to function returning char.
Forget about 1 and 2 - this is just theoretical.
3: This is used in the program entry function int main(int argc, char** argv). You can access a list of strings by using a char**. argv[0] = first string, argv[1] = second string, ...
Passing a pointer as an argument to a function lets that function change the contents of the variable pointed to, which can be useful for returning information by means other than the function return value. For example, the return value might already be used to indicate error/success, or you might want to return multiple values. The syntax for this in the calling code is foo(&var), which takes the address of var, i.e., a pointer to var.
So as such, if the variable whose contents you want the function to change is itself a pointer (e.g., a string), the parameter would be declared as a pointer to a pointer.
#include <stdio.h>
char *some_defined_string = "Hello, " ;
char *alloc_string() { return "World" ; } //pretend that it's dynamically allocated
int point_me_to_the_strings(char **str1, char **str2, char **str3)
{
*str1 = some_defined_string ;
*str2 = alloc_string() ;
*str3 = "!!" ;
if (str2 != 0) {
return 0 ; //successful
} else {
return -1 ; //error
}
}
main()
{
char *s1 ; //uninitialized
char *s2 ;
char *s3 ;
int success = point_me_to_the_strings(&s1, &s2, &s3) ;
printf("%s%s%s", s1, s2, s3) ;
}
Note that main() does not allocate any storage for the strings, so point_me_to_the_strings() does not write to str1, str2, and str3 as it would if they were passed as pointers to chars. Rather, point_me_to_the_strings() changes the pointers themselves, making them point to different places, and it can do this because it has pointers to them.