When should a double indirection be used in C? Can anyone explain with a example?
What I know is that a double indirection is a pointer to a pointer. Why would I need a pointer to a pointer?
If you want to have a list of characters (a word), you can use char *word
If you want a list of words (a sentence), you can use char **sentence
If you want a list of sentences (a monologue), you can use char ***monologue
If you want a list of monologues (a biography), you can use char ****biography
If you want a list of biographies (a bio-library), you can use char *****biolibrary
If you want a list of bio-libraries (a ??lol), you can use char ******lol
... ...
yes, I know these might not be the best data structures
Usage example with a very very very boring lol
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int wordsinsentence(char **x) {
int w = 0;
while (*x) {
w += 1;
x++;
}
return w;
}
int wordsinmono(char ***x) {
int w = 0;
while (*x) {
w += wordsinsentence(*x);
x++;
}
return w;
}
int wordsinbio(char ****x) {
int w = 0;
while (*x) {
w += wordsinmono(*x);
x++;
}
return w;
}
int wordsinlib(char *****x) {
int w = 0;
while (*x) {
w += wordsinbio(*x);
x++;
}
return w;
}
int wordsinlol(char ******x) {
int w = 0;
while (*x) {
w += wordsinlib(*x);
x++;
}
return w;
}
int main(void) {
char *word;
char **sentence;
char ***monologue;
char ****biography;
char *****biolibrary;
char ******lol;
//fill data structure
word = malloc(4 * sizeof *word); // assume it worked
strcpy(word, "foo");
sentence = malloc(4 * sizeof *sentence); // assume it worked
sentence[0] = word;
sentence[1] = word;
sentence[2] = word;
sentence[3] = NULL;
monologue = malloc(4 * sizeof *monologue); // assume it worked
monologue[0] = sentence;
monologue[1] = sentence;
monologue[2] = sentence;
monologue[3] = NULL;
biography = malloc(4 * sizeof *biography); // assume it worked
biography[0] = monologue;
biography[1] = monologue;
biography[2] = monologue;
biography[3] = NULL;
biolibrary = malloc(4 * sizeof *biolibrary); // assume it worked
biolibrary[0] = biography;
biolibrary[1] = biography;
biolibrary[2] = biography;
biolibrary[3] = NULL;
lol = malloc(4 * sizeof *lol); // assume it worked
lol[0] = biolibrary;
lol[1] = biolibrary;
lol[2] = biolibrary;
lol[3] = NULL;
printf("total words in my lol: %d\n", wordsinlol(lol));
free(lol);
free(biolibrary);
free(biography);
free(monologue);
free(sentence);
free(word);
}
Output:
total words in my lol: 243
One reason is you want to change the value of the pointer passed to a function as the function argument, to do this you require pointer to a pointer.
In simple words, Use ** when you want to preserve (OR retain change in) the Memory-Allocation or Assignment even outside of a function call. (So, Pass such function with double pointer arg.)
This may not be a very good example, but will show you the basic use:
#include <stdio.h>
#include <stdlib.h>
void allocate(int **p)
{
*p = (int *)malloc(sizeof(int));
}
int main()
{
int *p = NULL;
allocate(&p);
*p = 42;
printf("%d\n", *p);
free(p);
}
Let’s say you have a pointer. Its value is an address.
but now you want to change that address.
you could. by doing pointer1 = pointer2, you give pointer1 the address of pointer2.
but! if you do that within a function, and you want the result to persist after the function is done, you need do some extra work. you need a new pointer3 just to point to pointer1. pass pointer3 to the function.
here is an example. look at the output below first, to understand.
#include <stdio.h>
int main()
{
int c = 1;
int d = 2;
int e = 3;
int * a = &c;
int * b = &d;
int * f = &e;
int ** pp = &a; // pointer to pointer 'a'
printf("\n a's value: %x \n", a);
printf("\n b's value: %x \n", b);
printf("\n f's value: %x \n", f);
printf("\n can we change a?, lets see \n");
printf("\n a = b \n");
a = b;
printf("\n a's value is now: %x, same as 'b'... it seems we can, but can we do it in a function? lets see... \n", a);
printf("\n cant_change(a, f); \n");
cant_change(a, f);
printf("\n a's value is now: %x, Doh! same as 'b'... that function tricked us. \n", a);
printf("\n NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a' \n");
printf("\n change(pp, f); \n");
change(pp, f);
printf("\n a's value is now: %x, YEAH! same as 'f'... that function ROCKS!!!. \n", a);
return 0;
}
void cant_change(int * x, int * z){
x = z;
printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", x);
}
void change(int ** x, int * z){
*x = z;
printf("\n ----> value of 'a' is: %x inside function, same as 'f', BUT will it be the same outside of this function? lets see\n", *x);
}
Here is the output: (read this first)
a's value: bf94c204
b's value: bf94c208
f's value: bf94c20c
can we change a?, lets see
a = b
a's value is now: bf94c208, same as 'b'... it seems we can, but can we do it in a function? lets see...
cant_change(a, f);
----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see
a's value is now: bf94c208, Doh! same as 'b'... that function tricked us.
NOW! lets see if a pointer to a pointer solution can help us... remember that 'pp' point to 'a'
change(pp, f);
----> value of 'a' is: bf94c20c inside function, same as 'f', BUT will it be the same outside of this function? lets see
a's value is now: bf94c20c, YEAH! same as 'f'... that function ROCKS!!!.
Adding to Asha's response, if you use single pointer to the example bellow (e.g. alloc1() ) you will lose the reference to the memory allocated inside the function.
#include <stdio.h>
#include <stdlib.h>
void alloc2(int** p) {
*p = (int*)malloc(sizeof(int));
**p = 10;
}
void alloc1(int* p) {
p = (int*)malloc(sizeof(int));
*p = 10;
}
int main(){
int *p = NULL;
alloc1(p);
//printf("%d ",*p);//undefined
alloc2(&p);
printf("%d ",*p);//will print 10
free(p);
return 0;
}
The reason it occurs like this is that in alloc1 the pointer is passed in by value. So, when it is reassigned to the result of the malloc call inside of alloc1, the change does not pertain to code in a different scope.
I saw a very good example today, from this blog post, as I summarize below.
Imagine you have a structure for nodes in a linked list, which probably is
typedef struct node
{
struct node * next;
....
} node;
Now you want to implement a remove_if function, which accepts a removal criterion rm as one of the arguments and traverses the linked list: if an entry satisfies the criterion (something like rm(entry)==true), its node will be removed from the list. In the end, remove_if returns the head (which may be different from the original head) of the linked list.
You may write
for (node * prev = NULL, * curr = head; curr != NULL; )
{
node * const next = curr->next;
if (rm(curr))
{
if (prev) // the node to be removed is not the head
prev->next = next;
else // remove the head
head = next;
free(curr);
}
else
prev = curr;
curr = next;
}
as your for loop. The message is, without double pointers, you have to maintain a prev variable to re-organize the pointers, and handle the two different cases.
But with double pointers, you can actually write
// now head is a double pointer
for (node** curr = head; *curr; )
{
node * entry = *curr;
if (rm(entry))
{
*curr = entry->next;
free(entry);
}
else
curr = &entry->next;
}
You don't need a prev now because you can directly modify what prev->next pointed to.
To make things clearer, let's follow the code a little bit. During the removal:
if entry == *head: it will be *head (==*curr) = *head->next -- head now points to the pointer of the new heading node. You do this by directly changing head's content to a new pointer.
if entry != *head: similarly, *curr is what prev->next pointed to, and now points to entry->next.
No matter in which case, you can re-organize the pointers in a unified way with double pointers.
1. Basic Concept -
When you declare as follows : -
1. char *ch - (called character pointer)
- ch contains the address of a single character.
- (*ch) will dereference to the value of the character..
2. char **ch -
'ch' contains the address of an Array of character pointers. (as in 1)
'*ch' contains the address of a single character. (Note that it's different from 1, due to difference in declaration).
(**ch) will dereference to the exact value of the character..
Adding more pointers expand the dimension of a datatype, from character to string, to array of strings, and so on... You can relate it to a 1d, 2d, 3d matrix..
So, the usage of pointer depends upon how you declare it.
Here is a simple code..
int main()
{
char **p;
p = (char **)malloc(100);
p[0] = (char *)"Apple"; // or write *p, points to location of 'A'
p[1] = (char *)"Banana"; // or write *(p+1), points to location of 'B'
cout << *p << endl; //Prints the first pointer location until it finds '\0'
cout << **p << endl; //Prints the exact character which is being pointed
*p++; //Increments for the next string
cout << *p;
}
2. Another Application of Double Pointers -
(this would also cover pass by reference)
Suppose you want to update a character from a function. If you try the following : -
void func(char ch)
{
ch = 'B';
}
int main()
{
char ptr;
ptr = 'A';
printf("%c", ptr);
func(ptr);
printf("%c\n", ptr);
}
The output will be AA. This doesn't work, as you have "Passed By Value" to the function.
The correct way to do that would be -
void func( char *ptr) //Passed by Reference
{
*ptr = 'B';
}
int main()
{
char *ptr;
ptr = (char *)malloc(sizeof(char) * 1);
*ptr = 'A';
printf("%c\n", *ptr);
func(ptr);
printf("%c\n", *ptr);
}
Now extend this requirement for updating a string instead of character.
For this, you need to receive the parameter in the function as a double pointer.
void func(char **str)
{
strcpy(str, "Second");
}
int main()
{
char **str;
// printf("%d\n", sizeof(char));
*str = (char **)malloc(sizeof(char) * 10); //Can hold 10 character pointers
int i = 0;
for(i=0;i<10;i++)
{
str = (char *)malloc(sizeof(char) * 1); //Each pointer can point to a memory of 1 character.
}
strcpy(str, "First");
printf("%s\n", str);
func(str);
printf("%s\n", str);
}
In this example, method expects a double pointer as a parameter to update the value of a string.
Pointers to pointers also come in handy as "handles" to memory where you want to pass around a "handle" between functions to re-locatable memory. That basically means that the function can change the memory that is being pointed to by the pointer inside the handle variable, and every function or object that is using the handle will properly point to the newly relocated (or allocated) memory. Libraries like to-do this with "opaque" data-types, that is data-types were you don't have to worry about what they're doing with the memory being pointed do, you simply pass around the "handle" between the functions of the library to perform some operations on that memory ... the library functions can be allocating and de-allocating the memory under-the-hood without you having to explicitly worry about the process of memory management or where the handle is pointing.
For instance:
#include <stdlib.h>
typedef unsigned char** handle_type;
//some data_structure that the library functions would work with
typedef struct
{
int data_a;
int data_b;
int data_c;
} LIB_OBJECT;
handle_type lib_create_handle()
{
//initialize the handle with some memory that points to and array of 10 LIB_OBJECTs
handle_type handle = malloc(sizeof(handle_type));
*handle = malloc(sizeof(LIB_OBJECT) * 10);
return handle;
}
void lib_func_a(handle_type handle) { /*does something with array of LIB_OBJECTs*/ }
void lib_func_b(handle_type handle)
{
//does something that takes input LIB_OBJECTs and makes more of them, so has to
//reallocate memory for the new objects that will be created
//first re-allocate the memory somewhere else with more slots, but don't destroy the
//currently allocated slots
*handle = realloc(*handle, sizeof(LIB_OBJECT) * 20);
//...do some operation on the new memory and return
}
void lib_func_c(handle_type handle) { /*does something else to array of LIB_OBJECTs*/ }
void lib_free_handle(handle_type handle)
{
free(*handle);
free(handle);
}
int main()
{
//create a "handle" to some memory that the library functions can use
handle_type my_handle = lib_create_handle();
//do something with that memory
lib_func_a(my_handle);
//do something else with the handle that will make it point somewhere else
//but that's invisible to us from the standpoint of the calling the function and
//working with the handle
lib_func_b(my_handle);
//do something with new memory chunk, but you don't have to think about the fact
//that the memory has moved under the hood ... it's still pointed to by the "handle"
lib_func_c(my_handle);
//deallocate the handle
lib_free_handle(my_handle);
return 0;
}
Hope this helps,
Jason
Strings are a great example of uses of double pointers. The string itself is a pointer, so any time you need to point to a string, you'll need a double pointer.
Simple example that you probably have seen many times before
int main(int argc, char **argv)
In the second parameter you have it: pointer to pointer to char.
Note that the pointer notation (char* c) and the array notation (char c[]) are interchangeable in function arguments. So you could also write char *argv[]. In other words char *argv[] and char **argv are interchangeable.
What the above represents is in fact an array of character sequences (the command line arguments that are given to a program at startup).
See also this answer for more details about the above function signature.
A little late to the party, but hopefully this will help someone.
In C arrays always allocate memory on the stack, thus a function can't return
a (non-static) array due to the fact that memory allocated on the stack
gets freed automatically when the execution reaches the end of the current block.
That's really annoying when you want to deal with two-dimensional arrays
(i.e. matrices) and implement a few functions that can alter and return matrices.
To achieve this, you could use a pointer-to-pointer to implement a matrix with
dynamically allocated memory:
/* Initializes a matrix */
double** init_matrix(int num_rows, int num_cols){
// Allocate memory for num_rows float-pointers
double** A = calloc(num_rows, sizeof(double*));
// return NULL if the memory couldn't allocated
if(A == NULL) return NULL;
// For each double-pointer (row) allocate memory for num_cols floats
for(int i = 0; i < num_rows; i++){
A[i] = calloc(num_cols, sizeof(double));
// return NULL if the memory couldn't allocated
// and free the already allocated memory
if(A[i] == NULL){
for(int j = 0; j < i; j++){
free(A[j]);
}
free(A);
return NULL;
}
}
return A;
}
Here's an illustration:
double** double* double
------------- ---------------------------------------------------------
A ------> | A[0] | ----> | A[0][0] | A[0][1] | A[0][2] | ........ | A[0][cols-1] |
| --------- | ---------------------------------------------------------
| A[1] | ----> | A[1][0] | A[1][1] | A[1][2] | ........ | A[1][cols-1] |
| --------- | ---------------------------------------------------------
| . | .
| . | .
| . | .
| --------- | ---------------------------------------------------------
| A[i] | ----> | A[i][0] | A[i][1] | A[i][2] | ........ | A[i][cols-1] |
| --------- | ---------------------------------------------------------
| . | .
| . | .
| . | .
| --------- | ---------------------------------------------------------
| A[rows-1] | ----> | A[rows-1][0] | A[rows-1][1] | ... | A[rows-1][cols-1] |
------------- ---------------------------------------------------------
The double-pointer-to-double-pointer A points to the first element A[0] of a
memory block whose elements are double-pointers itself. You can imagine these
double-pointers as the rows of the matrix. That's the reason why every
double-pointer allocates memory for num_cols elements of type double.
Furthermore A[i] points to the i-th row, i.e. A[i] points to A[i][0] and
that's just the first double-element of the memory block for the i-th row.
Finally, you can access the element in the i-th row
and j-th column easily with A[i][j].
Here's a complete example that demonstrates the usage:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Initializes a matrix */
double** init_matrix(int num_rows, int num_cols){
// Allocate memory for num_rows double-pointers
double** matrix = calloc(num_rows, sizeof(double*));
// return NULL if the memory couldn't allocated
if(matrix == NULL) return NULL;
// For each double-pointer (row) allocate memory for num_cols
// doubles
for(int i = 0; i < num_rows; i++){
matrix[i] = calloc(num_cols, sizeof(double));
// return NULL if the memory couldn't allocated
// and free the already allocated memory
if(matrix[i] == NULL){
for(int j = 0; j < i; j++){
free(matrix[j]);
}
free(matrix);
return NULL;
}
}
return matrix;
}
/* Fills the matrix with random double-numbers between -1 and 1 */
void randn_fill_matrix(double** matrix, int rows, int cols){
for (int i = 0; i < rows; ++i){
for (int j = 0; j < cols; ++j){
matrix[i][j] = (double) rand()/RAND_MAX*2.0-1.0;
}
}
}
/* Frees the memory allocated by the matrix */
void free_matrix(double** matrix, int rows, int cols){
for(int i = 0; i < rows; i++){
free(matrix[i]);
}
free(matrix);
}
/* Outputs the matrix to the console */
void print_matrix(double** matrix, int rows, int cols){
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
printf(" %- f ", matrix[i][j]);
}
printf("\n");
}
}
int main(){
srand(time(NULL));
int m = 3, n = 3;
double** A = init_matrix(m, n);
randn_fill_matrix(A, m, n);
print_matrix(A, m, n);
free_matrix(A, m, n);
return 0;
}
For example, you might want to make sure that when you free the memory of something you set the pointer to null afterwards.
void safeFree(void** memory) {
if (*memory) {
free(*memory);
*memory = NULL;
}
}
When you call this function you'd call it with the address of a pointer
void* myMemory = someCrazyFunctionThatAllocatesMemory();
safeFree(&myMemory);
Now myMemory is set to NULL and any attempt to reuse it will be very obviously wrong.
For instance if you want random access to noncontiguous data.
p -> [p0, p1, p2, ...]
p0 -> data1
p1 -> data2
-- in C
T ** p = (T **) malloc(sizeof(T*) * n);
p[0] = (T*) malloc(sizeof(T));
p[1] = (T*) malloc(sizeof(T));
You store a pointer p that points to an array of pointers. Each pointer points to a piece of data.
If sizeof(T) is big it may not be possible to allocate a contiguous block (ie using malloc) of sizeof(T) * n bytes.
One thing I use them for constantly is when I have an array of objects and I need to perform lookups (binary search) on them by different fields.
I keep the original array...
int num_objects;
OBJECT *original_array = malloc(sizeof(OBJECT)*num_objects);
Then make an array of sorted pointers to the objects.
int compare_object_by_name( const void *v1, const void *v2 ) {
OBJECT *o1 = *(OBJECT **)v1;
OBJECT *o2 = *(OBJECT **)v2;
return (strcmp(o1->name, o2->name);
}
OBJECT **object_ptrs_by_name = malloc(sizeof(OBJECT *)*num_objects);
int i = 0;
for( ; i<num_objects; i++)
object_ptrs_by_name[i] = original_array+i;
qsort(object_ptrs_by_name, num_objects, sizeof(OBJECT *), compare_object_by_name);
You can make as many sorted pointer arrays as you need, then use a binary search on the sorted pointer array to access the object you need by the data you have. The original array of objects can stay unsorted, but each pointer array will be sorted by their specified field.
Why double pointers?
The objective is to change what studentA points to, using a function.
#include <stdio.h>
#include <stdlib.h>
typedef struct Person{
char * name;
} Person;
/**
* we need a ponter to a pointer, example: &studentA
*/
void change(Person ** x, Person * y){
*x = y; // since x is a pointer to a pointer, we access its value: a pointer to a Person struct.
}
void dontChange(Person * x, Person * y){
x = y;
}
int main()
{
Person * studentA = (Person *)malloc(sizeof(Person));
studentA->name = "brian";
Person * studentB = (Person *)malloc(sizeof(Person));
studentB->name = "erich";
/**
* we could have done the job as simple as this!
* but we need more work if we want to use a function to do the job!
*/
// studentA = studentB;
printf("1. studentA = %s (not changed)\n", studentA->name);
dontChange(studentA, studentB);
printf("2. studentA = %s (not changed)\n", studentA->name);
change(&studentA, studentB);
printf("3. studentA = %s (changed!)\n", studentA->name);
return 0;
}
/**
* OUTPUT:
* 1. studentA = brian (not changed)
* 2. studentA = brian (not changed)
* 3. studentA = erich (changed!)
*/
The following is a very simple C++ example that shows that if you want to use a function to set a pointer to point to an object, you need a pointer to a pointer. Otherwise, the pointer will keep reverting to null.
(A C++ answer, but I believe it's the same in C.)
(Also, for reference: Google("pass by value c++") = "By default, arguments in C++ are passed by value. When an argument is passed by value, the argument's value is copied into the function's parameter.")
So we want to set the pointer b equal to the string a.
#include <iostream>
#include <string>
void Function_1(std::string* a, std::string* b) {
b = a;
std::cout << (b == nullptr); // False
}
void Function_2(std::string* a, std::string** b) {
*b = a;
std::cout << (b == nullptr); // False
}
int main() {
std::string a("Hello!");
std::string* b(nullptr);
std::cout << (b == nullptr); // True
Function_1(&a, b);
std::cout << (b == nullptr); // True
Function_2(&a, &b);
std::cout << (b == nullptr); // False
}
// Output: 10100
What happens at the line Function_1(&a, b);?
The "value" of &main::a (an address) is copied into the parameter std::string* Function_1::a. Therefore Function_1::a is a pointer to (i.e. the memory address of) the string main::a.
The "value" of main::b (an address in memory) is copied into the parameter std::string* Function_1::b. Therefore there are now 2 of these addresses in memory, both null pointers. At the line b = a;, the local variable Function_1::b is then changed to equal Function_1::a (= &main::a), but the variable main::b is unchanged. After the call to Function_1, main::b is still a null pointer.
What happens at the line Function_2(&a, &b);?
The treatment of the a variable is the same: within the function, Function_2::a is the address of the string main::a.
But the variable b is now being passed as a pointer to a pointer. The "value" of &main::b (the address of the pointer main::b) is copied into std::string** Function_2::b. Therefore within Function_2, dereferencing this as *Function_2::b will access and modify main::b . So the line *b = a; is actually setting main::b (an address) equal to Function_2::a (= address of main::a) which is what we want.
If you want to use a function to modify a thing, be it an object or an address (pointer), you have to pass in a pointer to that thing. The thing that you actually pass in cannot be modified (in the calling scope) because a local copy is made.
(An exception is if the parameter is a reference, such as std::string& a. But usually these are const. Generally, if you call f(x), if x is an object you should be able to assume that f won't modify x. But if x is a pointer, then you should assume that f might modify the object pointed to by x.)
Compare modifying value of variable versus modifying value of pointer:
#include <stdio.h>
#include <stdlib.h>
void changeA(int (*a))
{
(*a) = 10;
}
void changeP(int *(*P))
{
(*P) = malloc(sizeof((*P)));
}
int main(void)
{
int A = 0;
printf("orig. A = %d\n", A);
changeA(&A);
printf("modi. A = %d\n", A);
/*************************/
int *P = NULL;
printf("orig. P = %p\n", P);
changeP(&P);
printf("modi. P = %p\n", P);
free(P);
return EXIT_SUCCESS;
}
This helped me to avoid returning value of pointer when the pointer was modified by the called function (used in singly linked list).
OLD (bad):
int *func(int *P)
{
...
return P;
}
int main(void)
{
int *pointer;
pointer = func(pointer);
...
}
NEW (better):
void func(int **pointer)
{
...
}
int main(void)
{
int *pointer;
func(&pointer);
...
}
Most of the answers here are more or less related to application programming. Here is an example from embedded systems programming. For example below is an excerpt from the reference manual of NXP's Kinetis KL13 series microcontroller, this code snippet is used to run bootloader, which resides in ROM, from firmware:
"
To get the address of the entry point, the user application reads the word containing the pointer to the bootloader API tree at offset 0x1C of the bootloader's vector table. The vector table is placed at the base of the bootloader's address range, which for the ROM is 0x1C00_0000. Thus, the API tree pointer is at address 0x1C00_001C.
The bootloader API tree is a structure that contains pointers to other structures, which have the function and data addresses for the bootloader. The bootloader entry point is always the first word of the API tree.
"
uint32_t runBootloaderAddress;
void (*runBootloader)(void * arg);
// Read the function address from the ROM API tree.
runBootloaderAddress = **(uint32_t **)(0x1c00001c);
runBootloader = (void (*)(void * arg))runBootloaderAddress;
// Start the bootloader.
runBootloader(NULL);
I have used double pointers today while I was programming something for work, so I can answer why we had to use them (it's the first time I actually had to use double pointers). We had to deal with real time encoding of frames contained in buffers which are members of some structures. In the encoder we had to use a pointer to one of those structures. The problem was that our pointer was being changed to point to other structures from another thread. In order to use the current structure in the encoder, I had to use a double pointer, in order to point to the pointer that was being modified in another thread. It wasn't obvious at first, at least for us, that we had to take this approach. A lot of address were printed in the process :)).
You SHOULD use double pointers when you work on pointers that are changed in other places of your application. You might also find double pointers to be a must when you deal with hardware that returns and address to you.
Related
I'm trying to read some float values as an array to a struct member as shown below:
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <stdio.h>
#define MAX_IN 10
typedef struct S_t S_t;
struct S_t {
float *sptr;
uint32_t ns;
};
S_t *getInputS(char *sdfile)
{
FILE *inSFP;
float fvls[MAX_IN];
static S_t inS;
int n;
inSFP = fopen(sdfile, "r");
if (inSFP == NULL) {
printf("\nFailed to open input file...!!!\n");
}
else {
n = 0;
while (fscanf(inSFP, "%f", &fvls[n]) != EOF) {
printf("fvls[%d] = %f\n", n, fvls[n]);
n++;
}
printf("\nScanned all inputs....\n");
inS.ns = (uint32_t) n;
inS.sptr = (float *) malloc(n * sizeof(float));
inS.sptr = fvls;
for(int i = 0; i < n; i++)
printf("inS.sptr[%d] = %f\n", i, inS.sptr[i]);
printf("\nInput read from file %s....\n", sdfile);
fclose(inSFP);
printf("\nClosed file...");
}
return &inS;
}
int main(int argc, char *argv[])
{
S_t *inpS = malloc(sizeof(*inpS));
inpS->sptr = malloc(MAX_IN * sizeof(inpS->sptr));
S_t *outS = malloc(sizeof(*outS));
outS->sptr = malloc(MAX_IN * sizeof(outS->sptr));
static uint32_t n;
char *inFN = argv[1];
char *outFN = argv[2];
inpS = getInputS(inFN);
printf("\nContent from main : \n");
n = inpS->ns;
for(int i = 0; i < n; i++)
printf("%f", *(inpS->sptr + i));
// printf("%f", inpS->sptr[i]);
printf("\nS structure updated (ns = %d)....\n", n);
return 0;
}
This returns the following:
fvls[0] = 0.430000
fvls[1] = 0.563210
fvls[2] = 0.110000
fvls[3] = 1.230000
fvls[4] = -0.034000
Scanned all inputs....
inS.sptr[0] = 0.430000
inS.sptr[1] = 0.563210
inS.sptr[2] = 0.110000
inS.sptr[3] = 1.230000
inS.sptr[4] = -0.034000
Input read from file in.txt....
Closed file...
Content from main :
-0.0000000.0000000.0000000.000000-nan
S structure updated (ns = 5)....
Input values (Original Input):
[0.000000, 0.000000, -0.000000, 0.000000, -0.000000]
The values are indeed read from the input file by the function getInputS() correctly, but on return the member sptr's values are returned incorrectly.
I am using a static variable of type S_t to store the values so that the value is retained. Inspite of that, the values seem to have lost! What am I doing wrong here? How do I fix this?
In this line:
inS.sptr = (float *) malloc(n * sizeof(float));
you cause sptr to point to a malloc'ed region of just the right size for your inputs.
That's good.
But in the very next line:
inS.sptr = fvls;
you throw the malloc'ed pointer away, overwriting it with a pointer to the local fvls array, which is going to disappear when this function returns.
Stated another way: when you store a pointer in a pointer variable, it's just like storing any other value in any other variable. Any time you do something like this:
a = b;
a = c;
you are throwing away the effect of the first assignment, and when you're done, all a is left holding is the value of c. It's no different when a is a pointer variable and b and c are two different pointer values.
Whenever you work with pointers, you have to keep clear in your mind the distinction between the pointer and what the pointer points to. In your getInputS function, you have to worry about both: you have to set the pointer sptr to point to valid storage to contain the values you've read, and you have to set what the pointer points to to be those values. When you say
inS.sptr = (float *) malloc(n * sizeof(float));
you're setting the pointer. But when you say
inS.sptr = fvls;
you're resetting the pointer to something else. But you never get around to setting what the pointer points to (the first, malloc'ed pointer, that is) at all.
And, to be clear, the line
inS.sptr = fvls;
copies the pointer, it does not copy the pointed-to data, which is what you need at this point.
To fix this, either:
Copy data from fvls to sptr (in place of the line inS.sptr = fvls). You can call memcpy, or you can use a loop repeatedly assigning sptr[i] = fvls[i].
Get rid of fvls, initialize sptr to malloc(MAX_IN * sizeof(float));, read directly into sptr, and then at the end, if you want to try to minimize wasted space, call realloc to reallocate sptr down to just big enough for the number of values you actually read.
I'm learning C myself and stumble upon a "strange" behavior. I'm trying to replicate the list data structure of Python, using C.
For the header file listint.h, I have this:
#include "stdint.h"
#ifndef LISTINT_H
#define LISTINT_H
typedef struct { // simple list of int
int ** list; // void pointer to the array of pointer
uint32_t length; // size of the list
} ListInt;
void ListInt_print(ListInt * self);
void ListInt_append(ListInt * self, int * item); // add pointer of an item - pointer to the list
#endif
For the listint.c (compiled to liblistint.so), there is implementation of the ListInt_append:
#include "stdlib.h"
#include "stdio.h"
#include "listint.h"
void ListInt_append(ListInt * self, int * item) {
if (self->list == NULL) { // uninitialized list
int ** ptr;
ptr = malloc(sizeof(int *));
self->list = ptr;
ptr[0] = item;
self->length = 1;
return;
} else if (item != NULL) {
int ** list_tmp; // temp list for realloc
uint32_t new_size = self->length + 1;
int ** ptr;
if ((list_tmp = realloc(self->list, sizeof(int *) * new_size)) == NULL) {
return;
};
self->list = list_tmp;
list_tmp[new_size - 1] = item;
self->length = new_size;
return;
};
return;
};
For the test file, I have tried two versions:
The first one, I declare two variables of type ListInt list this:
#include "stdio.h"
#include "stdlib.h"
#include "listint.h"
void main() {
ListInt mlist1;
ListInt mlist2;
printf("mlist1.list address %p\n", mlist1.list);
printf("mlist2.list address %p\n", mlist2.list);
printf("mlist1.length value %d\n", mlist1.length);
printf("mlist2.length value %d\n", mlist2.length);
}
Output:
mlist1.list address (nil)
mlist2.list address 0x7ffc3c4d3e20
mlist1.length value -1701232544
mlist2.length value 0
Moreover, if I added this:
int a = 5;
int b = 7;
ListInt_append(&mlist1, &a);
ListInt_append(&mlist2, &b);
The ListInt_append(&mlist2, &b); will return realloc() invalid pointer
The second one, declaring the two pointers:
ListInt * mlist1 = malloc(sizeof(ListInt));
ListInt * mlist2 = malloc(sizeof(ListInt));
The initial values of attributes:
mlist1.list address (nil)
mlist2.list address (nil)
mlist1.length value 0
mlist2.length value 0
Running the following worked as expected:
int a = 5;
int b = 7;
ListInt_append(&mlist1, &a);
ListInt_append(&mlist2, &b);
It seems I'm missing st very fundamental here. Plz pardon my lack of understanding. Thanks in advance.
Objects defined with ListInt mlist1; and ListInt mlist2; inside functions are not given initial values. Their initial values are indeterminate, and the program behavior is generally not defined by the C standard when you attempt to use the values. (If the address of the object is taken, the program behavior becomes somewhat defined, but the value remains indeterminate.)
You can give them initial values with:
ListInt mlist1 = { 0, 0 }; // Initialize members in order.
ListInt mlist1 = { .list = 0, .length = 0; } // Initialize by member name.
Similarly, with malloc, no initial value is given. After allocation, you can give the structures values by assigning to their members, as with:
mlist1->list = 0;
mlist1->length = 0;
Alternately, you can have the memory set to all zeros by using ListInt *mlist1 = calloc(1, sizeof *mlist1); instead of using malloc. That usually suffices, although technically it is not specified that all-zero bytes represents a null pointer, so the assignment method is more portable in theory.
If the objects were declared outside of a function or with static, as in static ListInt mlist1;, they would have static storage duration and would automatically be initialized with initial values of zero (including setting pointers to a null pointer value).
I'm trying to learn the memory allocation in C using malloc and increasing the size of allocated array using realloc inside a function. I came across this. when I use single variable the code is working well. But when I allocate memory for second variable, it gives me weird output.
Code is below:
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
# define N 3
void padd(int *a){
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
}
int main()
{
int *d;
int *pA;
int size = N*sizeof(int);
pA = (void *)malloc(size);
//d = (int *)malloc(size);
padd(pA);
printf("outside func= %d",pA[0]);
}
it gives me output:
inside func= 10
outside func= 10
but if I uncomment the //d = (int *)malloc(size); line, It gives me
inside func= 10
outside func= -1368048824
as output.
What might be wrong here?
If realloc can’t extend a buffer in place, it will allocate a new buffer, copy the contents of the old buffer to it, free the old buffer, and return the address of the new buffer (or NULL if it cannot satisfy the request); thus, the value of a can change in padd. However, that change is only applied to the formal parameter a - the actual parameter pA is not affected.
Based on the behavior, it looks like that if you allocate d, it’s allocated immediately after pA such that pA can’t be extended in place, so realloc is creating a new buffer and deallocating the old one, and the old buffer is overwritten before the printf statement in main.
You’ll want to write padd such that any changes to a are reflected in pA - either return the (potentially new) value of a or pass a pointer to pA:
void padd( int **a )
{
size_t sizes = 10 * sizeof (int); // see note 1
int *tmp = realloc( *a, sizes ); // see note 2
if ( tmp )
{
*a = tmp;
(*a)[0] = 10;
printf( "Inside func, (*a)[0] = %d\n", (*a)[0] );
}
else
{
printf ( "Inside func, realloc failed!\n" );
}
}
and you’d call it as
padd( &pA );
Note 1: sizeof has type size_t, not int.
Note 2: Since realloc can potentially return NULL, always assign the result to a temporary value and check it before assigning back to the original variable, otherwise you run the risk of losing access to memory you’ve already allocated. Also, the cast to void * is unnecessary and confusing since you’re assigning the result to an int * variable. Unless you’re compiling this code as C++ or under an ancient K&R C compiler, just leave the cast off completely - otherwise, your cast has to match the type of the thing you’re assigning to, which in this case is int *.
You should either get the new pointer back from padd:
int * padd(int * a){
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
return a;
}
//...
int main()
{
//...
pA = padd(pA);
//...
}
Or pass a pointer to the pointer:
void padd(int **pA){
int *a = *pA;
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
*pA = a;
}
//...
int main()
{
//...
padd(&pA);
//...
}
The both your programs have undefined behavior.
The function parameter a
void padd(int *a)
is a local variable of the function that is initialized by the value of the pointer pA used as a function argument in the function call
padd(pA);
You can imagine the function definition and its call the following way
padd(pA);
//...
void padd( /* int *a */ ){
int *a = pA;
int sizes = 10*sizeof(int);
a = (void *)realloc(a,sizes);
a[0] = 10;
printf("inside func= %d \n",a[0]);
}
So as it is seen changing the local variable a within the function padd does not influence on the value stored in the pointer pA because the function deals with a copy of the value of the pointer pA.
To change the original pointer pA within the function you need to pass it to the function by reference.
In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer you will get a direct access to the object.
The function should be declared and defined the following way
int padd( int **a ){
int sizes = 10*sizeof(int);
int *tmp = realloc( *a, size );
int success = tmp != NULL;
if ( success )
{
*a = tmp;
( *a )[0] = 10;
// or **a = 10;
printf("inside func= %d \n", ( *a )[0] );
}
return success;
}
And the function can be called like
if ( padd( &pA () ) printf("outside func= %d",pA[0]);
Pay attention to that to call realloc you should use an intermediate variable because in general the function can return a null pointer. So reassigning the original pointer with a null pointer results in the original value of the pointer will be lost.
Also you should free all the dynamically allocated memory when it is not needed any more
free( pA );
I've some problems of segmentation fault with this code:
void init(int max, pile * p) {
p = (pile *)malloc(sizeof(pile));
if(p){
p->nbElemPresent = 0;
p->maxElem = max;
p->tete = (data *)malloc(max * sizeof(data));
}
}
short int vide(pile * p) {
if(p->maxElem == 0) {return 1;}
return 0;
}
my function vide return me segfault.. I don't know how to access to struct member from the p pointer.
The main program:
pile * p;
init(5, p);
printf("%d", vide(p));
ty.
as already said, p is a new variable in your init function. other than the other answers suggested, i'd rather suggest not taking p as an argument at all, but instead returning it:
pile* init(int max) {
pile *p = (pile *)malloc(sizeof(pile));
...
return p;
}
and in your main function:
pile * p = init(5);
printf("%d", vide(p));
C takes parameters by value, that means that pointer p is copied when you pass it to init().
p in the function is a completely new variable and if its value is changed that doesn't change the value of p passed to the function.
You should pass its address:
init(5, &p);
void init(int max, pile** p) {
*p = malloc(sizeof(pile));
if(*p){
(*p)->nbElemPresent = 0;
....
}
}
Note the unusual parenthesis (*p)->nbElemPresent, this is done because -> operator has a higher precedence, yet we want to dereference the p first.
As said by barak manos, your problem lies in init. C pass parameters by value so let's imagine :
you set a pointer to pile to NULL (pile *p = NULL;)
you pass it to init (init(p);)
in init you alloc a pile and affect is to the local copy of p
on return from init, p is still NULL and you have a memory leak since you have no longer any pointer to the allocated pile
That's the reason why you should write :
void init(int max, pile ** p) {
pile *lp = *p = (pile *)malloc(sizeof(pile));
if(*p){
lp->nbElemPresent = 0;
lp->maxElem = max;
lp->tete = (data *)malloc(max * sizeof(data));
}
}
Now you use :
pile *p;
init(&p);
and on return p points to the allocated pile.
I am trying to have dynamically allocate arrays of structures and perform operations on them but i keep running into segmentation faults. could someone help me out?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *malloc(size_t size);
typedef struct {
double x;
double y;
} coords;
struct figure {
char fig_name[128];
int coordcount, size_tracker;
coords *pointer;
} fig;
void init_fig(int n, struct figure **point)
{
printf("%u\n", sizeof(coords));
point[n]->pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n]->pointer == NULL){
exit(-1);
}
point[n]->pointer[19].x = 2;
point[n]->pointer[0].x = 1;
point[n]->pointer[0].y = 2;
point[n]->pointer[7].x = 100;
}
int main()
{
int numfigs = 1;
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
point = &fig;
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
I labelled where the first seg fault occurs, (used ddd). what i dont get is that i can manipulate point[1] in main but not in any other function.
I agree with #Maxim Skurydin.
Nevertheless I'd like to explain your mistake in some more details.
Reading your init_fig one assumes that the parameter you pass struct figure **point - is actually array of pointers to struct figure. And this function accesses its n'th element.
However in your main you do something else. You allocate an array of struct figure, and your point variable points to its head. Then you take the address of this local variable and call your init_fig.
Here's the problem. init_fig assumes that you pass it an array of pointers, whereas actually this "array" consists of a single element only: the local point variable declared in main.
EDIT:
How to do this properly.
Leave main intact, fix init_fig.
This means that actually there's an array of figure structs. Means - a single memory block, interpreted as an array of consequent structs.
void init_fig(int n, struct figure *point)
{
printf("%u\n", sizeof(coords));
point[n].pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n].pointer == NULL){
exit(-1);
}
point[n].pointer[19].x = 2;
point[n].pointer[0].x = 1;
point[n].pointer[0].y = 2;
point[n].pointer[7].x = 100;
}
Leave init_fig intact. Fix main.
This means that we actually should allocate an array of pointers, every such a pointer should point to an allocated point structure.
int main()
{
int numfigs = 1;
struct figure ** point;
point = malloc(sizeof(struct figure*) * 16);
for (i = 0; i < 16; i++)
point[i] = malloc(sizeof(struct figure));
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
You allocate memory and store the pointer in point but then you forget that pointer when you assign &fig to it.
point = malloc(sizeof(struct figure) * 16);
point = &fig;
So, you are essentially trying to write fig[1], that does not make sense.
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
here point is pointer pointing to memory of 16 structures in heap
but in the next line you have done this
point = &fig;
so its memory leak and also point is not pointing to that allocated region anymore
and also init_fig should be like this
void init_fig(int n, struct figure **point)
It's the problem of segfault
Eliminate this line point = &fig;
and modify the function:
void init_fig(int n, struct figure *point)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
...
}
since you should pass an array of structs and not an array of pointers.
Also, add a third parameter to the init_fig function so you can pass the size of the array of points that you want to create. Like :
void init_fig(int n, struct figure *point, int size)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * size);
...
}
Therefore, making the function more reusable.
Modify also the call to that function:
init_fig(numfigs, &point); to init_fig(numfigs, point);