How to access a value pointed by pointer to pointer - c

I want to access the pointer to an array of pointers
I am successfullay able to map the top and the bottom block
unsigned int *outputAddress = NULL;
unsigned int *outputOffsetAddress = NULL;
unsigned int *OutputptrptrAddr = NULL;
unsigned int *PtrArr[250];
unsigned int **val = PtrArr;
void MemoryMapping(unsigned int outputOffsetRTI)
{
unsigned int *memBase;
memBase = (unsigned int *)malloc(2000);
outputAddress = (unsigned int *)(memBase + outputOffsetRTI);
for (int x = 0; x < 5; x++)
{
*outputAddress = 123;
*outputAddress++;
}
outputAddress = outputAddress - 5;
for (int x = 0; x < 5; x++)
{
PtrArr[x] = (unsigned int *)outputAddress;
outputAddress += 1;
}
outputOffsetAddress = outputAddress + 250;
for (int x = 0; x < 5; x++)
outputOffsetAddress[x] = (unsigned int)PtrArr[x];
}
How to tranverse through the input pointer block to get all values from the input block?

You need to dereference (e.g. *ptr) to access a value through a pointer. The following block illustrates the access you mention. But using triple pointers is not a good idea: Triple pointers in C: is it a matter of style?
// This is the pointer to an array of pointers
unsigned int *** input;
// Dereference it to get the array base
unsigned int ** ptr_array = *input;
// You can use a temporary pointer to iterate over the array
unsigned int * ptr;
// This will be the data pointed to
unsigned int data;
// You need to know the array size as well, assuming it is 5 here
for (int x=0; x<5; x++) {
// The array contains pointers
ptr = ptr_array[x];
// Dereference the pointer to reach the data
data = *ptr;
}

Related

Attempt to access elements of a 2d struct array failing

typedef struct{
unsigned long a;
unsigned long b;
unsigned long c;
} mini_struct;
struct ministruct** build_2Dstruct(unsigned long x, unsigned long y){
double x_squared = pow(2, x);
struct ministruct** temp = (mini_struct**)malloc(x*sizeof(mini_struct*));
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct*)malloc(y*sizeof(mini_struct));
for(int j = 0; j < y; j++){
temp[i][j].a = 0;
etc....
}
}
return temp;
}
In the code above I am trying to create a 2D array of ministructs**, with the whole struct being made out of 2^x ministructs*, and each ministruct* has y amount of ministructs.
aka:
x = 2,
y = 2,
[[struct, struct], [struct, struct], [struct, struct], [struct, struct]]
However, for some reason when I try to access the second element or index 1 of the struct inside each struct*, it says there is an error: "expression must be pointer to complete object".
I just do not understand why the code is not allowing me to access each individual element of the elements of the array?
Thanks
You are trying to make an x by y array of structs. So:
// create array of x pointers
mini_struct **temp = malloc(x*sizeof(mini_struct*));
for (int i=0; i<x; i++) {
// to array of y structs
temp[i] = malloc(y*sizeof(mini_struct));
for (int j=0; j < y; j++) {
temp[i][j].a = 0;
... etc.
Question is incomplete so I will be making asumptions.
You seem to be wanting to allocate a 2D array of structs and initialize all members to 0. Here is a possible solution:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
typedef struct mini_struct{
unsigned long a;
unsigned long b;
unsigned long c;
} mini_struct;
struct mini_struct** build_2Dstruct(unsigned long x, unsigned long y){
double x_squared = pow(x, 2);
mini_struct **temp = (mini_struct **) malloc(x_squared * sizeof(mini_struct*));
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct *) calloc(y, sizeof(mini_struct));
}
return temp;
}
int main () {
int x = 3;
int y = 4;
mini_struct **struct2D = build_2Dstruct(x, y);
int x_squared = pow(x,2);
for (int i = 0; i < x_squared; ++i) {
for (int j = 0; j < y; ++j) {
printf("Value of data stored at struct[%d][%d] is: %d\n", i, j, struct2D[i][j]);
}
}
for (int i = 0; i < x_squared; ++i) {
free(struct2D[i]);
}
free(struct2D);
}
As you can see, this contains the whole program, not just the snippet you showed. In this case, a main function would have been useful so that we don't have to guess what you want to do. My solution creates the 2D array with all elements initialized to 0 (you can use calloc to do that, no need for a second for loop).
Another important point is that, because the function returns a newly heap allocated 2D array, you need to free it to avoid a memory leak (end of main function).
You allocate x pointers to mini_struct:
mini_struct **temp = (mini_struct **) malloc(x_squared * sizeof(mini_struct*));
But then when you initialize them:
for(int i = 0; i < x_squared; i++){
temp[i] = (mini_struct *) calloc(y, sizeof(mini_struct));
}
You index temp based on upto x_squared.
Consider if x is 2. You would allocate temp to be an array of two pointers to mini_struct. But then your for loop would attempt to initialize four elements in temp.

Passing array of structs with reference - segmentation fault

#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X** a, int size){
for (int i = 0;i < size; i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container = (struct X*)malloc(sizeof(struct X) * n);
read_record(&container, n);
}
I created a 1D array of size n, then I passed it by reference to the function read_record. However, when I execute the program, there is a segmentation fault. What is the problem?
EDIT:
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. That's why I want to send the array as a reference. If I did it in main then I would write:
container = realloc(container, (n + 10) * sizeof(Struct X));
How can I do this in the function?
container is already a pointer, you don't need to pass the address-of the pointer, instead:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
void read_record(struct X *a, size_t size)
{
for (size_t i = 0; i < size; i++) {
a[i].deg = 0;
}
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
read_record(container, n);
}
also, prefer size_t to store the number of allocated objects.
Nitpick: read_record doesn't seem a good name for a function that modifies the contents of the records.
EDIT: As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
Same approach but returning a reallocated container:
#include <stdio.h>
#include <stdlib.h>
struct X {
char surname[30];
int deg;
};
struct X *read_record(struct X *a, size_t size)
{
struct X *new = realloc(a, sizeof(struct X) * size);
if (new != NULL)
{
for (size_t i = 0; i < size; i++) {
new[i].deg = 0;
}
}
return new;
}
int main(void)
{
size_t n = 10;
struct X *container = malloc(sizeof(struct X) * n);
container = read_record(container, n * 2);
if (container == NULL)
{
fprintf(stderr, "Can't read record\n");
exit(EXIT_FAILURE);
}
}
As a next step, I want to reallocate the array of 10 elements in the function with size of 20. (in the function). That's why I want to send the array as a reference.
The pointer is passed by value, so to save the changes and have them usable outside the function scope, after the function ends, i.e. in main, a pointer to pointer must be the argument, and the address of the pointer must be passed, your overall assessment is correct.
Your implementation, however, is not correct, here's how you shoud do it:
Live demo
void read_record(struct X **a, int size) //double pointer
{
*a = realloc(*a, sizeof **a * (size + 10)); //reallocate memory for 20 ints
if (*a == NULL)
{
perror("malloc");
}
for (int i = 0; i < size + 10; i++) //assing new values
{
(*a)[i].deg = 1;
}
}
int main()
{
int n = 10;
struct X *container = malloc(sizeof *container * n); //original allocation
//the pointer now has space for 10 ints
if (container == NULL)
{ //check allocation errors
perror("malloc");
}
for (int i = 0; i < n; i++) //assign values
{
container[i].deg = 0;
}
read_record(&container, n); //pass by reference
//the pointer now has space for 20 ints
}
Alternatively you can return the pointer instead, refering to David Ranieri's answer.
The first function parameter has the pointer to pointer type struct X**. So dereferencing the parameter a you will get a pointer of the type struct X*. Now you may apply the subscript operator that yields lvalue of the type struct X..
That is the function definition will look like
void read_record(struct X** a,int size){
for (int i=0;i<size;i++){
( *a )[i].deg = 0;
}
}
Or this statement
( *a )[i].deg = 0;
may be substituted for this statement
a[0][i].deg = 0;
On the other hand, there is no great sense to declare the first parameter as having the type struct X**. The function can look simpler as for example
void read_record(struct X* a,int size){
for (int i=0;i<size;i++){
a[i].deg = 0;
}
}
and be called like
read_record( container, n );
When you call read_record you pass a pointer to a pointer to the first element of an array of X structures.
But inside the read_record you treat it as a pointer to the first element of an array of pointers to X structures (i.e. as an array of pointers to X). There's a subtle but very important difference here.
If you want to emulate pass-by-reference for the pointer variable, you need to dereference it inside the read_record to get the original pointer (and remember that then you have an array of objects, not pointers):
(*a)[i].deg = 0;
Double pointer is the problem. The code should be:
void read_record(struct X* a,int size){ // Check the change
for (int i=0;i<size;i++){
a[i]->deg = 0;
}
}
int main(){
int n = 10;
struct X *container=(struct X*)malloc(sizeof(struct X)*n);
read_record(container,n); // Check the change
}

Converting unsigned char (array) to unsigned int (array)

I want to make a function that converts unsigned char to unsigned int and store it into an array. However, this ends up with an error that says
passing argument 1 of 'sprintf' from incompatible pointer type.
int main(void) {
unsigned char key[16] = "1234567812345678";
phex(key, 16); //store into an array here
}
uint64_t* phex(unsigned char* string, long len)
{
uint64_t hex[len];
int count = 0;
for(int i = 0; i < len; ++i) {
count = i * 2;
sprintf(hex + count, "%.2x", string[i]);
}
for(int i = 0; i < 32; i++)
printf(hex[i]);
return hex;
}
As comments have already said, you have problems in your code...
First of all sprintf function does totally opposite thing of what you want/expect it to do. Next, you create a local variable in your function, and return pointer to it.. As soon as function exits, pointer is invalid. Third problem I see is that you never assign return value to anything...
Proposition on how to fix your code:
unsigned* phex(unsigned char* string, long len);
int main(void) {
int i;
unsigned char key[16] = "1234567812345678";
unsigned* ints = phex(key,16); //store into an array here
for(i = 0; i < 16; i++)
printf("%d ", ints[i]);
//never forget to deallocate memory
free(ints);
return 0;
}
unsigned* phex(unsigned char* string, long len)
{
int i;
//allocate memory for your array
unsigned* hex = (unsigned*)malloc(sizeof(unsigned) * len);
for(i = 0; i < len; ++i) {
//do char to int conversion on every element of char array
hex[i] = string[i] - '0';
}
//return integer array
return hex;
}

Creating a method to convert a Pascal string in C using pointers

I've been working on a method which is supposed to convert a Pascal string to a C String. I was also told that the char * returned should point to a newly allocated char array containing a null-terminated C-String. The callee is responsible for calling free() on this array.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *pascal_convert(void *x)
{
int *y;
x = y;
char *z;
*z = *((int*)x);
char *arr = malloc(sizeof(*z));
for (int i = 0; i < *y; i++)
{
arr[i] = z[i];
}
char* fin = arr;
return fin;
}
Many adjustments needed
char *pascal_convert(void *x)
{
// int *y;
// x = y; This assignment is backwards
unsigned char *y = x; // Need unsigned char (unless your pascal uses wider type here)
// y = z;
// char *z;
// *z = *((int*)x);
size_t size = *y++; // Size is just the first element
// char *arr = malloc(sizeof(*z));
char *arr = malloc(size + 1); // Allocate + 1 for the null chacter
if (arr) { // test need as `malloc()` may fail
// for (int i = 0; i < *y; i++) { arr[i] = z[i]; }
memcpy(arr, y, size);
arr[size] = '\0'; // append null character
}
// char* fin = arr; // No need for new variable
// return fin;
return arr;
}

Memory allocation in my simple game [duplicate]

This question already has answers here:
Using malloc for allocation of multi-dimensional arrays with different row lengths
(8 answers)
Closed 9 years ago.
I'm writing the minesweeper game in C. I want be able to play games with different minefields with different sizes and number of mines
I've created such structures to describe my data:
typedef struct t_Place Place;
struct t_Place{
unsigned numberOfMinesNear;
int mine;
int state;
};
typedef struct t_Minefield Minefield;
struct t_Minefield{
int xSize;
int ySize;
unsigned minesNumber;
Place **places;
};
So, now I'm trying to initialize my minefield. I do the following:
void makeGame(Minefield *minefield, unsigned x, unsigned y, unsigned mines){
int i, j;
minefield->places = malloc(x * y * sizeof(Place));
for(i = 0; i < x; i++)
for(j = 0; j < y; j++){
minefield->places[i][j].mine = EMPTY;
minefield->places[i][j].state = HIDDEN;
minefield->places[i][j].numberOfMinesNear = 0;
}
minefield->xSize = x;
minefield->ySize = y;
unsigned minesToPlace = mines;
srand(time(NULL));
while(minesToPlace > 0){
i = rand() % x;
j = rand() % y;
if(minefield->places[i][j].mine)
continue;
minefield->places[i][j].mine = MINE;
minesToPlace--;
}
minefield->minesNumber = mines;
// here will be call of play(minefield) function to start the game
}
int main(){
Minefield *gameField = (Minefield *) malloc(sizeof(Minefield));
makeGame(gameField, DEFAULT_X, DEFAULT_Y, DEFAULT_MINES);
// DEFAULT_X = DEFAULT_Y = DEFAULT_MINES = 10
free(gameField);
return 0;
}
I'm getting segfault at first line of code in makeGame function. What i'm doing wrong? I want allocate memory for my minefield dynamically, not statically.
minefield->places = malloc(x * y * sizeof(Place));
The above memory allocation might be the source of the problem , places is a two star pointer , so there must be two malloc() calls , one to allocate the row number **place pointers , and then another malloc() , to allocate column number of *place pointers of type place.
Here is a SSCCE of allocating/initializing a two star pointer contained inside a structure.
#include <stdio.h>
#include <stdlib.h>
#define ROW_SZ 5
#define COL_SZ 25
typedef struct demo{
char **str;
}demo;
int main()
{
demo *d = malloc( sizeof(demo) );
d->str = malloc(ROW_SZ * sizeof(char*) ); //d->str is assigned char**
for ( i = 0; i < ROW_SZ; i++ )
d->str[i] = malloc(COL_SZ * sizeof(char) ); //d-str[i] is assigned char*
// code here to use d->str[ROW_SZ][COL_SZ]
for ( i = 0; i < ROW_SZ; i++ )
free(d->str[i]);
free(d->str);
free(d);
return 0;
}
This is how I usually see 2D arrays allocated:
minefield->places = malloc(x * sizeof(Place *));
for(i = 0; i < x; i++)
{
minefield->places[i] = malloc(x * sizeof(Place));
}
Try this and see if it makes you segfault vanish.

Resources