4I am trying to get a pointer address from a pointer to a pointer array, however I just get garbage when I run the code below. How do I retrieve the pointer address of one of the char * from the char ** array? Thanks for checking this out.
Specifically, I want to obtain the address of "wh" via "what" and assign it to "hi".
char * hi;
char * wh;
char ** what;
int main(void) {
char z[4] = "wx\0";
char a[4] = "ab\0";
hi = &z;
wh = &a;
what = (char **) malloc( 25 * sizeof(char));
what[0] = &hi;
what[1] = &wh;
printf("%s | %s\n", hi, wh);
hi = &what[1];
printf("%s | %s\n", hi, wh);
return EXIT_SUCCESS;
}
Corrected code:
#include <stdio.h>
#include<stdlib.h>
char * hi;
char * wh;
char ** what;
int main(void) {
char z[3] = "wx\0";
char a[3] = "ab\0";
hi = z;
wh = a;
what = malloc(2 * sizeof *what);
what[0] = hi;
what[1] = wh;
printf("%s | %s\n", hi, wh);
hi = what[1];
printf("%s | %s\n", hi, wh);
return 0;
}
The type of hi and wh is not the same as of &z and &a, even though they should yield the same value. Also you want what[1] in hi not the value of the memory location where it is. Also, in C you do not need to cast the return of malloc. However, in C++ the cast is required although its better to use the new operator.
Pointer Assignment
hi and wh are defined as pointer to char. So, change your assignment statements
from,
hi = &z; /* Type of &z is pointer-to-array-of-4-char */
wh = &a; /* Type of &a is pointer-to-array-of-4-char */
to,
hi = z; /* Type of z is pointer-to-char. Array name, here, decays into pointer
to first element of the array */
wh = a; /* Type of a is pointer-to-char */
what is defined as type, pointer to pointer to char. So, change your malloc statement
from,
what = (char **) malloc( 25 * sizeof(char)); /* what needs to hold char*'s,
you have allocated only for char's */
to,
what = malloc(25 * sizeof *what); /* what is of type char**. *what gives you char* */
Also, change your what , hi assignment statements
from,
what[0] = &hi; /* Type of what[0] is pointer-to-char;
Type of &hi is pointer-to-pointer-to-char */
what[1] = &wh; /* Type of what[1] is pointer-to-char;
Type of &wh is pointer-to-pointer-to-char */
...
hi = &what[1]; /* Type of hi is pointer-to-char;
Type of &what[1] is pointer-to-pointer-to-char */
to ,
what[0] = hi; /* Types are same */
what[1] = wh; /* Types are same */
...
hi = what[1]; /* Types are same */
Note:
The size of what is too high than what really required for the posted program. If you feel, you are going to have the same program, modify 25 to 2 in the malloc.
char * hi;
char * wh;
char ** what;
int main(void) {
char z[4] = "wx\0";
char a[4] = "ab\0";
hi = &z;
wh = &a;
First mistake; the types of the expressions &z and &a are both char (*)[4] (pointer to 4-element array of char), not char *. To fix this, drop the & from both:
hi = z;
wh = a;
Except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize an array, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression is the address of the first element in the array.
what = (char **) malloc( 25 * sizeof(char));
Don't cast the result of malloc; it isn't necessary1, and depending on the compiler version it can suppress a useful diagnostic. You also have a type mismatch. You want to space for 25 pointers to char, but you're only allocating enough for 25 plain chars. Rewrite that as
what = malloc( sizeof *what * 25 );
The type of the expression what is char **; thus, the type of the expression *what is char *. So sizeof *what will give you the same result as sizeof (char *). The above line allocates enough memory to store 25 pointers to char, and assigns the resulting pointer to what.
what[0] = &hi;
what[1] = &wh;
Again, drop the &; hi and wh are already pointers to char:
what[0] = hi;
what[1] = wh;
printf("%s | %s\n", hi, wh);
hi = &what[1];
Type mismatch; &what[1] has type char **, hi has type char *. Again, drop the &.
hi = what[1];
hi and wh now point to the same thing (what[1] == wh and hi == what[1], so hi == wh; that is, both hi and wh contain the same pointer value).
printf("%s | %s\n", hi, wh);
return EXIT_SUCCESS;
}
1. In C, that is; C++ is a different story, but if you're writing C++, you shouldn't be using malloc anyway.
Related
typedef struct PeoInfo
{
char name[20];
int age;
char sex[5];
char tele[12];
char addr[30];
}
struct PeoInfo c[10] = {0};
printf("p=%x\n", *c);
printf("p=%x\n", c[0]);
In this situation, sizeof(c) and sizeof(*c) have different results.
In my point of view, c is the entry of the array. But what is the *c? The result of sizeof(*c) is the size of PeoInfo. When using printf to print the address of *c and c[0], the result is also different.
I am really confused about it.
In this expression *c the array designator c is implicitly converted to a pointer to its first element of the type struct PeoInfo * and applying the dereference operator yields an object of the type struct PeoInfo.
So the expression sizeof( *c ) where the expression *c is not evaluated and only its type is determinated yields the size of an object of the type struct PeoInfo.
As the subscript operator c[0] is calculated like *( c + 0 ) that is the same as *c then these printf statements will output the same value
printf( "&*c = %p\n", ( void * )&*c );
printf( "&c[0] = %p\n", ( void * )&c[0] );
I call a function that swaps shifts a massage in memory:
for (int i = now->size - 1; i >= 0; i--)
{
void *address2 = prev->start_address + i;
void *address1 = now->start_adress + i;
address1 = address2;
address2 = '\0';
}
So basically I have two addresses one pointing to the first start location the other to the second start location that the content have to be pasted.
The problem is that the only solution that I find is to add int ( this is i value ) and prev->start_adress( that is void*) as I have shown. I want to do it correctly, i cant change the void pointer to int. Is there any other possibilities.
My errors:
error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive]
warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
214 | void *address2 = prev->start + i;
Warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
215 | void *address1 = now->start + i;
Supporting information:
I have a linked list(full of segementdescriptors) and a "memory" that is a simple array[].Similar how malloc works.
typedef struct segmentdescriptor
{
Byte allocated;
void *start;
size_t size;
struct segmentdescriptor *next;
} Node;
the start pointers point to the begining of the allocated space in the array[].
Update:
The simplest way is to use typecast to do arithmethics on void pointers if you know their size like :
char *address2 = (char *)prev->start + i;
If you dont know the type, it is impossible because for example:
char *pointer points to one byte of memory and if you write pointer++ goes
to next byte. int *pointer is lets say points four byes. if you write pointer ++ goes to the four bytes after the four bytes.
There are also good answers below.
Thanks for all answers.
I do not really understand what shifts a massage in memory is, but if you just want to copy one memory location to another you can
Use memcpy or memmove (if memory locations overlap)
memcpy(now->start_adress, prev->start_address, now->size);
Write your own function to copy the memory
void *mymemcpy(void *dest, const void *src, size_t size)
{
unsigned char *cdest = (unsigned char *)dest; //cast for C++ compiler
const unsigned char *csrc = (unsigned char *)src;
while(size--) *cdest++ = *csrc;
return dest;
}
void *mymemcpy(void *dest, const void *src, size_t size)
{
unsigned char *cdest = (unsigned char *)dest; //cast for C++ compiler
const unsigned char *csrc = (unsigned char *)src;
for(size_t index = 0; index < size; index++) cdest[index] = csrc[index];
return dest;
}
void *mymemcpy(void *dest, const void *src, size_t size)
{
unsigned char *cdest = (unsigned char *)dest; //cast for C++ compiler
const unsigned char *csrc = (unsigned char *)src;
for(size_t index = 0; index < size; index++) *(cdest + index) = *(csrc + index);
return dest;
}
C standard does not allow any pointer arithmetic on void pointers. gcc has an extension which treats the void * as pointer to char allowing the arithmetics, but not allowing dereferencing.+
The type void is always an incomplete type. That is the size of an object of the type void is unknown. So you may not use the pointer arithmetic with a pointer of the type void * though some compilers have their own language extensions that allow the pointer arithmetic with the type void * the same way as with pointers of the type char *.
So these statements
void *address2 = prev->start + i;
void *address1 = now->start + i;
are incorrect according to the C Standard because the pointer start has the type void *.
Also it seems these statements
address1 = address2;
address2 = '\0';
are doing not what you thing.
For starters this statement
address1 = address2;
assigns one pointer to another pointer though it looks like actually you want to assign a value pointed to by one pointer to the memory pointed to by another pointer.
And this statement is equivalent to
address2 = NULL;
That is it does not set the pointed memory with the terminating zero character '\0'.
If as you are saying these pointers deal with a message (a string) then you need to cast the pointers to the type char *.
As for this your phrase
I call a function that swaps shifts a massage in memory:
then it is totally unclear what you are trying to do using the for loop because the loop in any case does not make a sense.
If you need to copy one character array into another character array then use the standard C function memcpy or memmove depending on what and how you are trying to copy arrays.
Regarding these warnings:
warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
214 | void *address2 = prev->start + i;
Warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arit]
215 | void *address1 = now->start + i;
On any modern computer the value of a pointer is a memory address (typically a virtual memory address). When you add one to a pointer, it's value (aka the memory address) is incremented by the sizeof the pointed to type.
Example:
TYPE* p = SOME_ADDRESS; // The value of p is now SOME_ADDRESS
p = p + 1; // The value of p is now SOME_ADDRESS + sizeof(TYPE);
p = SOME_ADDRESS; // The value of p is now SOME_ADDRESS
p = p + i; // The value of p is now SOME_ADDRESS + i * sizeof(TYPE);
In other words: In order to add an integer value to a pointer, we need to know the size of the element that the pointer points to.
And that is your problem. You have void-pointers so you would need to know the "sizeof void" in order to update the pointer. But the sizeof void can be anything and isn't defined by the standard. Apparently, your compiler has a non-standard extension that allows sizeof(void). Consequently, your compiler only gives you a warning.
Regarding this error:
error: invalid conversion from ‘void*’ to ‘char*’
It comes from some code post you didn't post. Further it shows that you use a c++ compiler instead of a c compiler.
Finally: Even if the pointer arithmetic was valid, your code do nothing.
for (int i = now->size - 1; i >= 0; i--)
{
void *address2 = prev->start_address + i;
void *address1 = now->start_adress + i;
address1 = address2; // This only change the value of the pointer
// It doesn't change the memory that the
// pointer points to
address2 = '\0';
}
It's not fully clear what you are trying to do but perhaps this is what you are looking for:
for (int i = now->size - 1; i >= 0; i--)
{
char *address2 = (char*)prev->start_address + i;
char *address1 = (char*)now->start_adress + i;
*address1 = *address2;
*address2 = '\0';
}
Assume this code in C:
int a = 5;
int *b = &a;
*b = 6;
Notice that b had to be dereferenced using * to have a value reassigned.
However, the same doesn't go with a char pointer (a String):
char *name = "test";
name = "test2";
name did not have to be dereferenced. Why is that?
In this code snippet
int a = 5;
int *b = &a;
*b = 6;
the last assignment stores the integer constant to the object pointed to by the pointer b. That is the value of the object a is changed not the value (address) stored in the pointer b.
In this code snippet
char *name = "test";
name = "test2";
the value of the pointer itself is changed not the object pointed to by the pointer. So at first the pointer name pointed to the first character of the string literal "test" and then it is reassigned to point to the first character of the string literal "test2".
It is the similar to the following code
int a = 5;
int *b = &a;
int a2 = 6;
b = &a2;
If you want to change an object pointed to by a pointer of the type char * you could write
char s[] = "test";
char *name = s;
*name = 'T';
In this case the array s will have "Test".
Pay attention that you may not change a string literal. That is if instead of the array s you will write
char *s = "test";
char *name = s;
*name = 'T';
then the code will have undefined behavior.
Also bear in mind that in this declaration
char *s = "test";
the string literal having the type char[5] is implicitly converted to pointer to its first element.
The type of "test2" is already char[6] (which in turn decays to char*). There's simply no need to use address-of on the rvalue, or dereference the lvalue to do the assignment for the types to work out.
Why is that?
Because the two examples you show are not the same.
The were the same if you did:
/* your 1st example: */
int a = 5;
int *b = &a; /* b is a pointer to a what a is. */
*b = 6;
a equals 6 now.
/* your second example adjusted: */
char *a = "test";
char **b = &a; /* b is a pointer to a what a is. */
*b = "test2";
a points to "test2" now.
Please forgive me if the title is not 100% correct. I have a function which takes two inputs - a pointer to a string, and a pointer to a pointer to an array (?). The function I am writing is
int string_parser(char *inp, char **array_of_words[])
What I want to be doing is taking these two arguments and the function should return
the amount of words in the string array (string array is char *inp)
a pointer to an array of pointers char **array_of_words[] - each element in the array pointing to the address of the first character in each word (I apologise if that is wordy)
I have created the pointer to an array of pointers, and allocated space to this array
char **startOfWords_ptr = (char **) malloc(amountOfWords * sizeof(char*));
and have been manipulating the contents just fine. I now want to pass the array at *start_of_words back to array_of_words - but I don't understand how to do it
With *array_of_words = *(startOfWords_ptr); am I saying: a pointer to point at the starting address of the array of pointers?
Surely I am not because I don't get the same values when printing...
printf("%p\n", (void *) *array_of_words); // 0x401f2c, o
printf("%p\n", (void *) *startOfWords_ptr); // 0x401f2c, o
printf("%p\n", (void *) array_of_words[1]); // 0x401f2c, o
printf("%p\n", (void *) startOfWords_ptr[1]); // 0x401f30, t
Suggestions with comments as output
*array_of_words = (startOfWords_ptr); // This currently does not work
printf("%p, %c\n", (void *) array_of_words[0], *array_of_words[0]); // 0xcbbdd0, ;
printf("%p, %c\n", (void *) startOfWords_ptr[0], *startOfWords_ptr[0]); // 0x401f3b, o
printf("%p, %c\n", (void *) array_of_words[1], *array_of_words[1]); // 0x401f2c, o
printf("%p, %c\n", (void *) startOfWords_ptr[1], *startOfWords_ptr[1]); // 0x401f3f, t
Okay, so let's look at this from the perspective of the caller of this function:
int main( void )
{
char my_input[] = "This is a test";
char **my_output = NULL;
int count = string_parser( my_input, &my_output );
for ( int i = 0; i < count; i++ )
printf( "pointer #%d: %p\n", i, (void *) my_output[i] );
}
We know that after calling string_parser, my_output will point to the first of a sequence of pointers to char. Since we need to modify the value of my_output, we must pass a pointer to it in the call (&my_output).
This means that the prototype for string_parser needs to be
int string_parser( const char *inp, char ***array_of_words )
{
...
}
In the context of a function parameter declaration, T a[N] and T a[] are both treated as T *a, so char ***array_of_words is the same as char **array_of_words[] - both are ultimately char ***.
So given
I have created the pointer to an array of pointers, and allocated space to this array
char **startOfWords_ptr = (char **) malloc(amountOfWords * sizeof(char*));
and have been manipulating the contents just fine. I now want to pass the array at *start_of_words back to array_of_words - but I don't understand how to do it
you have it backwards - you'd assign the startOfWords_ptr to *array_of_words:
*array_of_words = startOfWords_ptr; // char ** = char **
array_of_words has one more level of indirection than startOfWords_ptr, so we need to dereference it to get the types to match. After this assignment,
*array_of_words[i] == startOfWords_ptr[i] // char * == char *
this parameter in the function signature:
char **array_of_words[]
can be re-written as:
char ***array_of_words
I.E. either write it as:
char **array_of_words
or as:
char *array_of_words[]
This is very similar to the different ways the second parameter to main() can be written.
I am having trouble understanding how to assign memory
to a double pointer.
I want to read an array of strings and store it.
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<20; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
instead of this I just assign a large block of memory and
store the string
char **ptr;
ptr = (char**)malloc(sizeof(char)*50*50);
would that be wrong? And if so why is it?
Your second example is wrong because each memory location conceptually would not hold a char* but rather a char. If you slightly change your thinking, it can help with this:
char *x; // Memory locations pointed to by x contain 'char'
char **y; // Memory locations pointed to by y contain 'char*'
x = (char*)malloc(sizeof(char) * 100); // 100 'char'
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*'
// below is incorrect:
y = (char**)malloc(sizeof(char) * 50 * 50);
// 2500 'char' not 50 'char*' pointing to 50 'char'
Because of that, your first loop would be how you do in C an array of character arrays/pointers. Using a fixed block of memory for an array of character arrays is ok, but you would use a single char* rather than a char**, since you would not have any pointers in the memory, just chars.
char *x = calloc(50 * 50, sizeof(char));
for (ii = 0; ii < 50; ++ii) {
// Note that each string is just an OFFSET into the memory block
// You must be sensitive to this when using these 'strings'
char *str = &x[ii * 50];
}
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<50; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
fclose(fp);
may be your typo mistake but your loop should be of 50 instead of 20 if you are looking for 50 x 50 matrix. Also after allocation of memory mentioned above you can access the buffer as ptr[i][j] i.e in the 2D format.
A double pointer is just a pointer to another pointer. So you can allocate it like this:
char *realptr=(char*)malloc(1234);
char **ptr=&realptr;
You have to keep in mind where your pointer is stored at (in this example the double pointer points to a pointer variable on the stack so it's invalid after the function returns).
i will give one example, which might clear of the doubt,
char **str; // here its kind a equivalent to char *argv[]
str = (char **)malloc(sizeof(char *)*2) // here 2 indicates 2 (char*)
str[0]=(char *)malloc(sizeof(char)*10) // here 10 indicates 10 (char)
str[1]=(char *)malloc(sizeof(char)*10) // <same as above>
strcpy(str[0],"abcdefghij"); // 10 length character
strcpy(str[1],"xyzlmnopqr"); // 10 length character
cout<<str[0]<<endl; // to print the string in case of c++
cout<<str[1]<<endl; // to print the string in case of c++
or
printf("%s",str[0]);
printf("%s",str[1]);
//finally most important thing, dont't forget to free the allocated mem
free(str[0]);
free(str[1]);
free(str);
other simpler way to memorize
Case -1 :
step-1 : char *p;
step -2 :
please read it like below
char (*p); ==> p is a pointer to a char
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char) * some_len);
Case -2 :
step-1 : char **p;
step -2 :
please read it like below
char* (* p); ==> p is a pointer to a char *
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char *) * some_len);
Case -3 :
No one uses this but just for sake of explanation
char ***p;
read it as,
char** (*p); ==> p is a pointer to a char** (and for this check case-2 above)
p = malloc(sizeof(char**) * some_len);
Adding to Pent's answer, as he correctly pointed out, you will not be able to use this double pointer once the function returns, because it will point to a memory location on the function's activation record on stack which is now obsolete (once the function has returned). If you want to use this double pointer after the function has returned, you may do this:
char * realptr = (char *) malloc(1234);
char ** ptr = (char **) malloc(sizeof(char *));
*ptr = realptr;
return ptr;
The return type of the function must obviously be char ** for this.
well, this is how I do it:
#include <stdlib.h>
int main(void)
{
int i = -1; // just a counter
int j = 5; // how many strings
char *s[j];
while(++i < j)
s[i] = malloc(sizeof(char*)); // allocating avery string separately
return (0);
}
this also works:
char **allocate(int lines)
{
int i = -1;
char **s = malloc(sizeof(char *) * lines); // allocating lines
while (++i < lines)
{
s[i] = malloc(sizeof(char*)); // alicating line
scanf("%s", s[i]);
}
return (s);
}
int main(int ac, char *av[])
{
int lines = 5; // how many lines
char **s = allocate(lines);
return (0);
}
Double pointer is, simply put, a pointer to a pointer,
In many cases it is used as an array of other types.
For example, if you want to create an array of strings you can simply do:
char** stringArray = calloc(10, 40);
this will create an array of size 10, each element will be a string of length 40.
thus you can access this by stringArray[5] and get a string in the 6th position.
this is one usage, the others are as mentioned above, a pointer to a pointer, and can be allocated simply by:
char* str = (char*)malloc(40);
char** pointerToPointer = &str //Get the address of the str pointer, valid only in the current closure.
read more here:
good array tutorial