how to use pointer to pointer to access pointer element in struct? - c

#include<stdlib.h>
typedef struct
{
int *member;
} mystruct;
void main(int argc, char *argv)
{
mystruct **data;
data = (mystruct**)malloc(sizeof(mystruct*));
int c = 5;
printf("%x", data);
(*data)->member = &c;
printf("Member: %d", *((*data)->member));
}
Error: Segmentation fault
I expected it would print "5" in the source code

Error: Segmentation fault
I expected it would print "5" in the source code
It is because you have only allocated a pointer to your struct and this pointer is not referencing a valid memory location. It invokes Undefined Behaviour (UB). You need to allocate the space for the structure itself.
int main(int argc, char *argv)
{
mystruct **data;
data = malloc(sizeof(*data));
*data = malloc(sizeof(**data));
int c = 5;
printf("%p %p", (void *)data, (void *)*data);
(*data)->member = &c;
printf("Member: %d", *((*data)->member)); //or*data[0]->member))
}
void main(.... is invalid
do not cast the result of malloc. If it does not compile - you use C++ compiler to compile C code which is wrong
use objects instead of types in sizeof
you have to use %p format to print pointers. Pointers have to be converted to void *

In this statement
data = (mystruct**)malloc(sizeof(mystruct*));
you allocated memory for one pointer of the type mystruct *. That is uninitialized.
Thus dereferencing this uninitialized pointer obtained by the expression *data
(*data)->member = &c
invokes undefined behavior.
At least you should write
data = (mystruct**)malloc(sizeof(mystruct*));
*data = malloc( sizeof( mystruct ) );
That is you need to allocate memory for an object of the type mystruct the data member member of which will be assigned.
Also pay attention to that using the conversion specifier %x to output a pointer
printf("%x", data);
also invokes undefined behavior. Instead you need to write
printf("%p\n", ( void * )data);
Or you could include header <inttypes.h> and write
#include <inttypes.h>
//...
printf("%" PRIxPTR "\n", ( uintptr_t )data);

Related

converting a string to a void pointer

I'm trying to figure out how to "transform" strings (char*) to void* and viceversa.
When I execute this my output is just the first printf and ignores the second one, it doesn't even write "after = "
PS This little program is just to understand, I know i could actually use swap(&s[0],&s[1]). I need to know how to properly cast a void pointer into an array of strings.
I'm working on a uni project where I need to create my own quick_sort algorythm and I need the swap function inside of it to work with void pointers.
#include <stdio.h>
#include <stdlib.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap((&array)[0],(&array)[1]);
printf("after = %s %s",(char*)array,(char*)array);
return 0;
}
I think I'm missing something big
Thanks in advance :D
In this declaration the array s used as an initializer is implicitly converted to a pointer to its first element of the type char **.
void* array = s;
In the call of the function swap
swap((&array)[0],(&array)[1]);
the first argument can be the pointer array itself that will be implicitly casted to the pointer type of the corresponding parameter
swap( array, (&array)[1]);
But you need to correctly pass the second argument. To do this you need to cast the pointer array explicitly like
swap( array, ( char ** )array + 1 );
In the call of printf you need also correctly to supply argument expressions.
Here is your updated program
#include <stdio.h>
static void swap(char** x,char** y);
static void swap(char** x,char** y){
char* temp=*x;
*x=*y;
*y=temp;
}
int main()
{
char* s[2];
s[0]="weee";
s[1]="yooo";
void* array=s;
printf("before %s %s\n",s[0],s[1]);
swap( array, ( char ** )array + 1 );
printf("after = %s %s", *(char**)array, ( (char**)array )[1]);
return 0;
}
The program output is
before weee yooo
after = yooo weee
void *array = s; declares array to be a void *. Then &array is the address of that void *, so &array[1] would access a void * after it. But there is no void * after it, since void *array defines a single void *.
array could be properly defined to alias s with char **array = s;, after which swap(&array[0], &array[1]); would work as desired.
If you define array as void **array = (void **) s;, then swap(&array[0], &array[1]); will produce diagnostic messages because the types are wrong. You could use swap((char **) &array[0], (char **) &array[1]);.
Then, if you print the strings with printf("after = %s %s", array[0], array[1]);, this will work, although it is not entirely proper code. Using array[0] as an argument passes a void * where printf is expecting a char * for the %s. However, the C standard guarantees that void * and char * have the same representation (encode their values using bytes in memory in the same way), and it further says (in a non-normative note) that this is intended to imply interchangeability as arguments to functions.
The void* doesn't seem to fulfil any particular purpose here, just swap the pointers: swap(&s[0],&s[1]);.
You could also do this:
char** ptr = &s[0];
printf("before %s %s\n",ptr[0],ptr[1]);
swap(&ptr[0],&ptr[1]);
printf("after = %s %s",ptr[0],ptr[1]);
If you for reasons unknown insist on using void* then note that as your code stands, it points at the first char* in your array of char*. However, it isn't possible to perform pointer arithmetic on void* since that would entail knowing how large a "void" is. The void* doesn't know that it points at an array of pointers. Therefore array[i] is nonsense.
Also, the void* are set to point at char* so you simply cannot pass it to a function expecting a char**. You'd have to rewrite the whole program in a needlessly obfuscated way, so just abandon that idea.

Why can't I access a pointer to pointer for a stack array?

Please take a look at the following code. It tries to pass an array as a char** to a function:
#include <stdio.h>
#include <stdlib.h>
static void printchar(char **x)
{
printf("Test: %c\n", (*x)[0]);
}
int main(int argc, char *argv[])
{
char test[256];
char *test2 = malloc(256);
test[0] = 'B';
test2[0] = 'A';
printchar(&test2); // works
printchar((char **) &test); // crashes because *x in printchar() has an invalid pointer
free(test2);
return 0;
}
The fact that I can only get it to compile by explicitly casting &test2 to char** already hints that this code is wrong.
Still, I'm wondering what exactly is wrong about it. I can pass a pointer to a pointer to a dynamically allocated array but I can't pass a pointer to a pointer for an array on the stack. Of course, I can easily work-around the problem by first assigning the array to a temporary variable, like so:
char test[256];
char *tmp = test;
test[0] = 'B';
printchar(&tmp);
Still, can someone explain to me why it doesn't work to cast char[256] to char** directly?
test is an array, not a pointer, and &test is a pointer to the array. It is not a pointer to a pointer.
You may have been told that an array is a pointer, but this is incorrect. The name of an array is a name of the entire object—all the elements. It is not a pointer to the first element. In most expressions, an array is automatically converted to a pointer to its first element. That is a convenience that is often useful. But there are three exceptions to this rule:
The array is the operand of sizeof.
The array is the operand of &.
The array is a string literal used to initialize an array.
In &test, the array is the operand of &, so the automatic conversion does not occur. The result of &test is a pointer to an array of 256 char, which has type char (*)[256], not char **.
To get a pointer to a pointer to char from test, you would first need to make a pointer to char. For example:
char *p = test; // Automatic conversion of test to &test[0] occurs.
printchar(&p); // Passes a pointer to a pointer to char.
Another way to think about this is to realize that test names the entire object—the whole array of 256 char. It does not name a pointer, so, in &test, there is no pointer whose address can be taken, so this cannot produce a char **. In order to create a char **, you must first have a char *.
Because test is not a pointer.
&test gets you a pointer to the array, of type char (*)[256], which is not compatible with char** (because an array is not a pointer). This results in undefined behavior.
The type of test2 is char *. So, the type of &test2 will be char ** which is compatible with the type of parameter x of printchar().
The type of test is char [256]. So, the type of &test will be char (*)[256] which is not compatible with the type of parameter x of printchar().
Let me show you the difference in terms of addresses of test and test2.
#include <stdio.h>
#include <stdlib.h>
static void printchar(char **x)
{
printf("x = %p\n", (void*)x);
printf("*x = %p\n", (void*)(*x));
printf("Test: %c\n", (*x)[0]);
}
int main(int argc, char *argv[])
{
char test[256];
char *test2 = malloc(256);
test[0] = 'B';
test2[0] = 'A';
printf ("test2 : %p\n", (void*)test2);
printf ("&test2 : %p\n", (void*)&test2);
printf ("&test2[0] : %p\n", (void*)&test2[0]);
printchar(&test2); // works
printf ("\n");
printf ("test : %p\n", (void*)test);
printf ("&test : %p\n", (void*)&test);
printf ("&test[0] : %p\n", (void*)&test[0]);
// Commenting below statement
//printchar((char **) &test); // crashes because *x in printchar() has an invalid pointer
free(test2);
return 0;
}
Output:
$ ./a.out
test2 : 0x7fe974c02970
&test2 : 0x7ffee82eb9e8
&test2[0] : 0x7fe974c02970
x = 0x7ffee82eb9e8
*x = 0x7fe974c02970
Test: A
test : 0x7ffee82eba00
&test : 0x7ffee82eba00
&test[0] : 0x7ffee82eba00
Point to note here:
The output (memory address) of test2 and &test2[0] is numerically same and their type is also same which is char *.
But the test2 and &test2 are different addresses and their type is also different.
The type of test2 is char *.
The type of &test2 is char **.
x = &test2
*x = test2
(*x)[0] = test2[0]
The output (memory address) of test, &test and &test[0] is numerically same but their type is different.
The type of test is char [256].
The type of &test is char (*) [256].
The type of &test[0] is char *.
As the output shows &test is same as &test[0].
x = &test[0]
*x = test[0] //first element of test array which is 'B'
(*x)[0] = ('B')[0] // Not a valid statement
Hence you are getting segmentation fault.
You cannot access a pointer to a pointer because &test is not a pointer—it's an array.
If you take the address of an array, cast the array and the address of the array to (void *), and compare them, they will (barring possible pointer pedantry) be equivalent.
What you're really doing is similar to this (again, barring strict aliasing):
putchar(**(char **)test);
which is quite obviously wrong.
Your code expects the argument x of printchar to point to memory that contains a (char *).
In the first call, it points to the storage used for test2 and is thus indeed a value that points to a (char *), the latter pointing to the allocated memory.
In the second call, however, there is no place where any such (char *) value might be stored and so it is impossible to point to such memory. The cast to (char **) you added would have removed a compilation error (about converting (char *) to (char **)) but it would not make storage appear out of thin air to contain a (char *) initialized to point to the first characters of test. Pointer casting in C does not change the actual value of the pointer.
In order to get what you want, you have to do it explicitly:
char *tempptr = &temp;
printchar(&tempptr);
I assume your example is a distillation of a much larger piece of code; as an example, perhaps you want printchar to increment the (char *) value that the passed x value points to so that on the next call the next character is printed. If that isn't the case, why don't you just pass a (char *) pointing to the character to be printed, or even just pass the character itself?
Apparently, taking the address of test is the same as taking the address of test[0]:
#include <stdio.h>
#include <stdlib.h>
static void printchar(char **x)
{
printf("[printchar] Address of pointer to pointer: %p\n", (void *)x);
printf("[printchar] Address of pointer: %p\n", (void *)*x);
printf("Test: %c\n", **x);
}
int main(int argc, char *argv[])
{
char test[256];
char *test2 = malloc(256);
printf("[main] Address of test: %p\n", (void *)test);
printf("[main] Address of the address of test: %p\n", (void *)&test);
printf("[main] Address of test2: %p\n", (void *)test2);
printf("[main] Address of the address of test2: %p\n", (void *)&test2);
test[0] = 'B';
test2[0] = 'A';
printchar(&test2); // works
printchar(&test); // crashes because *x in printchar() has an invalid pointer
free(test2);
return 0;
}
Compile that and run:
forcebru$ clang test.c -Wall && ./a.out
test.c:25:15: warning: incompatible pointer types passing 'char (*)[256]' to
parameter of type 'char **' [-Wincompatible-pointer-types]
printchar(&test); // crashes because *x in printchar() has an inva...
^~~~~
test.c:4:30: note: passing argument to parameter 'x' here
static void printchar(char **x)
^
1 warning generated.
[main] Address of test: 0x7ffeeed039c0
[main] Address of the address of test: 0x7ffeeed039c0 [THIS IS A PROBLEM]
[main] Address of test2: 0x7fbe20c02aa0
[main] Address of the address of test2: 0x7ffeeed039a8
[printchar] Address of pointer to pointer: 0x7ffeeed039a8
[printchar] Address of pointer: 0x7fbe20c02aa0
Test: A
[printchar] Address of pointer to pointer: 0x7ffeeed039c0
[printchar] Address of pointer: 0x42 [THIS IS THE ASCII CODE OF 'B' in test[0] = 'B';]
Segmentation fault: 11
So the ultimate cause of the segmentation fault is that this program will try to dereference the absolute address 0x42 (also known as 'B'), which your program doesn't have permission to read.
Although with a different compiler/machine the addresses will be different: Try it online!, but you'll still get this, for some reason:
[main] Address of test: 0x7ffd4891b080
[main] Address of the address of test: 0x7ffd4891b080 [SAME ADDRESS!]
But the address that causes the segmentation fault may very well be different:
[printchar] Address of pointer to pointer: 0x7ffd4891b080
[printchar] Address of pointer: 0x9c000000942 [WAS 0x42 IN MY CASE]
The representation of char [256] is implementation dependent. It is must not be the same as char *.
Casting &test of type char (*)[256] to char ** yields undefined behavior.
With some compilers, it may do what you expect, an on others not.
EDIT:
After testing with gcc 9.2.1, it appears that printchar((char**)&test) passes in fact test as value cast to char**. It is as if the instruction was printchar((char**)test). In the printchar function, x is a pointer to the first char of the array test, not a double pointer to the first character. A double de-reference x result in a segmentation fault because the 8 first bytes of the array do not correspond to a valid address.
I get the exact same behavior and result when compiling the program with clang 9.0.0-2.
This may be considered as a compiler bug, or the result of an undefined behavior whose result might be compiler specific.
Another unexpected behavior is that the code
void printchar2(char (*x)[256]) {
printf("px: %p\n", *x);
printf("x: %p\n", x);
printf("c: %c\n", **x);
}
The output is
px: 0x7ffd92627370
x: 0x7ffd92627370
c: A
The weird behavior is that x and *x have the same value.
This is a compiler thing. I doubt that this is defined by the language.

Why do I get garbage values from a structure initialized from void**

I test this code:
void foo (void* data[])
{
static struct structure
{
char character;
int integer;
} st1 = *((struct structure *)data);
printf("[%i][%c]", st1.integer, st1.character);
}
int main (void)
{
void* *data = calloc(2, sizeof(void* ));
char arg1 = 'b';
int arg2 = 20;
data[0] = (char* )&arg1;
data[1] = (int* ) &arg2;
foo(data);
return(0);
}
but I get garbage values instead of the intended
[20] [b]
I have tried many things, including st1 = *((struct structure *)&data);, (despite that AFAIK data is already an address) declaring and initializing separate structure pointer and then deref-ing it, but nothing works.
What could be the reason this happens and how should I do it properly approaching the same idea of obtaining function arguments ?
You generally and portably can't expect your struct to be the same size as two void*.
You can't expect any specific padding inside the struct itself. And you can't expect that casting a char to void* will produce the same valid char back when the memory region is reinterpreted as part of a struct.
The behavior of (the code I think I read) is as undefined as it can get.
I originally completely overlooked the fact that you assign addresses to the two void* (imagined you cast the char and int themselves to void*), so your reinterpretation of those values need to not result in what you expect at all. In fact, it may result in trap values. So your code is undefiend behavior.
Your problem is located in your structure itself.
In your data, in main, you wrote an int* and a char*. However, in your function, you define the struct as it contains a char and int, what you should write is :
void foo (void* data[])
{
static struct structure
{
char* character;
int* integer;
} st1 = *((struct structure *)data);
printf("[%i][%c]", *(st1.integer), *(st1.character));
}

How structure pointer will assigned to zero with out having pointee address and find sizeof structure in below code?

#include <stdio.h>
struct test
{
int a;
char b;
int c;
};
int main()
{
struct test *ptr = (struct test *)0;
ptr++;
fprintf(stderr, "by pointer = %zd\n", (size_t) ptr);
fprintf(stderr, "by sizeof = %zd\n", sizeof(struct test));
return 0;
}
The behaviour on incrementing ptr in your case is undefined.
Note that (size_t)ptr is implementation defined. It is always valid to cast a pointer to size_t, however if the result cannot be represented by type size_t, the behavior is undefined.
The C standard allows you to set a pointer to 0, but pointer arithmetic is only valid in arrays, with the exception that you are allowed to point one past the end of an array or one past the address of a scalar.
Note that the correct format specifier for a sizeof type is %zu - else you have the potential for even more undefined behaviour.

Want to access struct pointer's data of type from struct's memory in C

My program dynamically allocates nodes of type struct pointer. I want to access the data of struct pointer via it's memory address. The main purpose of my question is to test b-tree insert with split. Here is the struct:
struct LeafNode
{
int EmpID[M];
int Location[M];
int keys;
};
typedef struct LeafNode* LNodePtr;
Here is my test code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int * a = (int *)malloc(sizeof(int));
*a = 5;
printf("int a created at %p\n", (void *) &a);
void * addr;
printf("Give the memory address: ");
scanf("%p", addr);
void * addr2 = (void *)addr;
printf("The value at memory is: %d\n",*(int*)addr2);
return 0;
}
Here' s the result:
int a created at 0xbff573b4
Give the memory address: 0xbff583b4
Segmentation fault
The second step is to cast to LNodePtr instead of int. I don't know if we can use double cast, i.e
*(int *(LNodePtr))addr
so that i can access
struct's EmpID[0]
int member through memory. Thanks for help.
void * addr;
Allocates a pointer, but does not initialize it.
scanf("%p", addr);
Reads a pointer into the variable stored at the address held in addr. You did not initialize addr so this is undefined behaviour.
Perhaps you meant to write:
scanf("%p", &addr);
But it's very hard to tell. Not least because you talk at length about a struct and then have code that does not mention the struct and instead works with void*.
printf("int a created at %p\n", (void *) &a);
This prints the address of the variable holding the pointer a. If you want to print the value of the pointer, use a instead of &a.
You shouldn't dereference a in your printf line, a itself is already a pointer, *a is the int!
printf("int a created at %p\n", (void *) a);
Also, you should dereference the void* in scanf
scanf("%p", &addr);
As a general tip, try compiling with the C flag -Wall, so you can easily catch these mistakes.
To answer the question in the comments, in case you have the node address 0x1234, you could do this:
MyNode *node = 0x1234;
node->int[0] = 5;
Hope that answers the question

Resources