Store pointer value - c

As I know, when a pointer is passed into a function, it becomes merely a copy of the real pointer. Now, I want the real pointer to be changed without having to return a pointer from a function. For example:
int *ptr;
void allocateMemory(int *pointer)
{
pointer = malloc(sizeof(int));
}
allocateMemory(ptr);
Another thing, which is, how can I allocate memory to 2 or more dimensional arrays? Not by subscript, but by pointer arithmetic. Is this:
int array[2][3];
array[2][1] = 10;
the same as:
int **array;
*(*(array+2)+1) = 10
Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself. For example:
int *a;
why not:
allocateMemory(*a)
but
allocateMemory(a)
I know I always have to do this, but I really don't understand why. Please explain to me.
The last thing is, in a pointer like this:
int *a;
Is a the address of the memory containing the actual value, or the memory address of the pointer? I always think a is the memory address of the actual value it is pointing, but I am not sure about this. By the way, when printing such pointer like this:
printf("Is this address of integer it is pointing to?%p\n",a);
printf("Is this address of the pointer itself?%p\n",&a);

I'll try to tackle these one at a time:
Now, I want the real pointer to be changed without having to return a pointer from a function.
You need to use one more layer of indirection:
int *ptr;
void allocateMemory(int **pointer)
{
*pointer = malloc(sizeof(int));
}
allocateMemory(&ptr);
Here is a good explanation from the comp.lang.c FAQ.
Another thing, which is, how can I allocate memory to 2 or more dimensional arrays?
One allocation for the first dimension, and then a loop of allocations for the other dimension:
int **x = malloc(sizeof(int *) * 2);
for (i = 0; i < 2; i++)
x[i] = malloc(sizeof(int) * 3);
Again, here is link to this exact question from the comp.lang.c FAQ.
Is this:
int array[2][3];
array[2][1] = 10;
the same as:
int **array;
*(*(array+2)+1) = 10
ABSOLUTELY NOT. Pointers and arrays are different. You can sometimes use them interchangeably, however. Check out these questions from the comp.lang.c FAQ.
Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself?
why not:
allocateMemory(*a)
It's two things - C doesn't have pass-by-reference, except where you implement it yourself by passing pointers, and in this case also because a isn't initialized yet - if you were to dereference it, you would cause undefined behaviour. This problem is a similar case to this one, found in the comp.lang.c FAQ.
int *a;
Is a the address of the memory containing the actual value, or the memory address of the pointer?
That question doesn't really make sense to me, but I'll try to explain. a (when correctly initialized - your example here is not) is an address (the pointer itself). *a is the object being pointed to - in this case that would be an int.
By the way, when printing such pointer like this:
printf("Is this address of integer it is pointing to?%p\n",a);
printf("Is this address of the pointer itself?%p\n",&a);
Correct in both cases.

To answer your first question, you need to pass a pointer to a pointer. (int**)
To answer your second question, you can use that syntax to access a location in an existing array.
However, a nested array (int[][]) is not the same as a pointer to a pointer (int**)
To answer your third question:
Writing a passes the value of the variable a, which is a memory address.
Writing *a passes the value pointed to by the variable, which is an actual value, not a memory address.
If the function takes a pointer, that means it wants an address, not a value.
Therefore, you need to pass a, not *a.
Had a been a pointer to a pointer (int**), you would pass *a, not **a.

Your first question:
you could pass a pointer's address:
void allocateMemory(int **pointer) {
*pointer = malloc(sizeof(int));
}
int *ptr;
allocateMemory(&ptr);
or you can return a pointer value:
int *allocateMemory() {
return malloc(sizeof(int));
}
int *ptr = mallocateMemory();

I think you're a little confused about what a pointer actually is.
A pointer is just variable whose value represents an address in memory. So when we say that int *p is pointer to an integer, that just means p is a variable that holds a number that is the memory address of an int.
If you want a function to allocate a buffer of integers and change the value in the variable p, that function needs to know where in memory p is stored. So you have to give it a pointer to p (i.e., the memory address of p), which itself is a pointer to an integer, so what the function needs is a pointer to a pointer to an integer (i.e., a memory address where the function should store a number, which in turn is the memory address of the integers the function allocated), so
void allocateIntBuffer(int **pp)
{
// by doing "*pp = whatever" you're telling the compiler to store
// "whatever" not in the pp variable but in the memory address that
// the pp variable is holding.
*pp = malloc(...);
}
// call it like
int *p;
allocateIntBuffer(&p);
I think the key to your questions is to understand that there is nothing special about pointer variables. A pointer is a variable like any other, only that the value stored in that variable is used to represent a position in memory.

Note that returning a pointer or forcing the caller to move the pointer in an out of a void * temp variable is the only way you can make use of the void * type to allow your function to work with different pointer types. char **, int **, etc. are not convertible to void **. As such, I would advise against what you're trying to do, and instead use the return value for functions that need to update a pointer, unless your function by design only works with a specific type. In particular, simple malloc wrappers that try to change the interface to pass pointer-to-pointer types are inherently broken.

Related

How to properly allocate memory for an array pointer passed as an argument in C

I am mixed up on my pointers and references. I want to create a pointer in a main function and set it to null. I would like to pass that pointer to another function that creates an array on the heap, fills it, and returns the size of the created array.
I tried to find another article about this topic but failed to find one that allocated memory from within the function. The example code below illustrates the concept but I am not writing a program to accomplish any specific task.
int fillarray(/* pointer to an array */){
// malloc the array to size n
// fill array with n elements
return n;
}
int main(){
int* array = NULL;
int size = fillarray(/* pass the pointer by reference */);
for(int i = 0; i < size; i++) printf("%d\n", array[i]);
free(array);
return 0;
}
UPDATE:
Thank you all for your comments. I learned a ton about pointers working through this problem. The code below accomplishes what I need it to. Thank you #Lundin. Your answer led me to the actual solution. Thank you #ssd as well. Your visual helped me gain some intuition on what I was looking at in the code.
int fillarray(int** array){
*array = (int*)malloc(2 * sizeof(int));
(*array)[0] = 0;
(*array)[1] = 1;
return 2;
}
int main(){
int* array = NULL;
int size = fillarray(&array);
for(int i = 0; i < size; i++) printf("%d\t", array[i]);
return 0;
}
Strictly speaking there are no "references" in C, everything is passed by value. Although the term "pass by reference" is language agnostic and really just means pass an address to the data. (C++ has a language concept called references, but it's really just glorified read-only pointers.)
So to achieve what you want, you have to pass the address of the pointer itself. That way, the function can access the pointer and set it to point at a new address. Thus declare the function as int fillarray (int**)call the function as fillarray(&array). The result of malloc needs to be assigned to where the pointer-to-pointer points at - it points at the address of the original pointer declared variable in main().
As for allocating a variable size, you will have to add an additional plain integer parameter to the function for that.
I do agree & consent Lundin's answer but to be more conceptual, I'll add the drawing below, for I had the same pain in the past understanding pointers.
The first integer pointer below (int *a) is at memory address 4c4b40 and its value is set to zero (which means this pointer a is set to null).
The second integer pointer (int *b) is at memory address 4c4b48 and its value is set to 4c4b58 (which means, this pointer points to memory address 4c4b58 with a length of integer). If that address corresponds to variable int x = 16 (hexadecimal 10 is equal to 16), then dereferencing pointer b will give you an integer value of 16 (*b = 16 because x = 16).
The third memory is another character string pointer, which points to a memory address somewhere down below.
Returning to the answer:
If you are to change the address of the first pointer (a) in order to point to the variable x, then the function you're calling needs to receive the address of the pointer (not the pointer, itself); i.e. &a instead of a, which corresponds to 4c4b40. The function called will receive the address 4c4b40 as a memory address and change its value from 000000 to 4c4b58. The function decoration, of course, will contain an int **; for, if an integer pointer is an int *, a pointer to a pointer will be an int **.

function which returns a pointer to a pointer to a pointer to an int in C

I'm trying to learn pointers in c and have been trying to write samples of code for different types of situations that involve pointers that I have found in this C book
in "Examples of pointer constructs" but I can't seem to figure out how to return a pointer to a pointer to a pointer to an int from a function or how to dereference such a pointer in main.
I have been searching for a simple example all over but couldn't find one to make it clear for me. Could anyone explain this concept and how such pointers work inside functions?
I've had no problems returning a pointer to int from a function and understood the process but higher levels gave me a hard time.
I've been trying to write very basic examples but I can't manage to store what this function returns in main, and also how I should dereference it:
int ***func(int x) {
int n = x * x;
int *p1, **p2, ***p3;
p1 = &n;
p2 = &p1;
p3 = &p2;
return &p3;
}
You have one more level of indirection at the end than you need:
return &p3;
p3 has type int ***, which matches the return value of the function. However you're returning the address of p3 which has type int ****. That's a type mismatch. You can correct this by just returning p3:
return p3;
Assuming for a moment that the pointer you return is valid (as well as all intermediate pointers), the you would assign the return value of the function to a variable of type int ***. Then you would have to dereference 3 times to get the actual integer value:
int ***rval = func(2);
printf("value=%d\n", ***rval);
There's a bigger problem here however, and that's that you're not returning valid pointers. The pointer value you're returning contains the address of a local variable (i.e. the address of p2). When the function returns that variable goes out of scope and thus its address is invalid. Attempting to dereference a pointer to an out of scope variable is undefined behavior.
For the memory you're pointing to to be valid after the function returns, you would need to dynamically allocate memory using malloc.
Also, it's very rare that you'd actually need a triple pointer (i.e. int ***). If you find yourself using a variable of this type, that's a good sign that you need to rethink your design.

What are the differences between pointer variable's value & address of normal variable and what are the special purpose of pointers in C?

This may be a very basic question but the idea of having pointers in C seems confusing to me or may be I don't know the exact purpose. I will provide some examples to demonstrate what my concerns are:
1st point:
Definition says something like this:
A pointer is a variable containing the address of another variable.
So, if one program goes like this:
int i = 23;
printf("%d", i);
printf("%d", &i);
And, another program goes like this:
int i = 23;
int *ptr;
ptr = &i;
printf("%d", *ptr);
printf("%d", ptr);
Both the programs above can output same thing.
If pointer also keeps the variable's address in it and at the same time we can get the variable's address using & sign, can't we do the same task pointer does by deriving the address of any variable? I mean if I don't declare it as pointer and use it as int ptr = &i; in 2nd code snippet and use it as normal variable, what would be the differences?
2nd point:
I found somewhere here that:
C does not have array variables....but this is really just working
with pointers with an alternative syntax.
Is that statement correct? As I am still beginner, I can't validate any statement regarding this. But this was somewhat confusing to me. If that statement is correct either, then what is the actual workaround in this regard? Is it actually the pointers which works in back-end and just the compilers/ide are fooling us by using array (obviously for maintaining simplicity)?
Answering questions in reverse order:
C does not have array variables....but this is really just working with pointers with an alternative syntax.
This is incorrect, and you need to toss that bookmark in the trash. It's a common misconception that arrays and pointers are the same thing, but they are not. An array expression will be converted to a pointer expression under most circumstances, and array subscripting is accomplished through pointer arithmetic, but an array object is an actual array, not a pointer.
If pointer also keeps the variable's address in it and at the same time we can get the variable's address using & sign, can't we do the same task pointer does by deriving the address of any variable? I mean if I don't declare it as pointer and use it as int ptr = &i; in 2nd code snippet and use it as normal variable, what would be the differences?
That code doesn't illustrate why pointers exist, or why they are useful.
C actually requires us to use pointers in the following cases:
To write to a function's parameters;
To track dynamically allocated memory;
Pointers also make dynamic data structures like trees and lists easy to implement, but they aren't required for it (unless you're using dynamic memory allocation in those structures).
Writing to a function's parameters
C passes all function arguments by value; the formal parameter in the function definition is a separate object in memory from the actual parameter in the function call, so any change to the formal parameter is not reflected in the actual parameter. For example, assume the following swap function:
void swap( int a, int b ) { int t = a; a = b; b = t; }
This function exchanges the values in a and b. However, when we call the function as
int x = 4, y = 5;
swap( x, y );
the values of x and y won't be updated, because they are different objects than a and b. If we want to update x and y, we have to pass pointers to them:
swap( &x, &y );
and update the function definition as follows:
void swap( int *a, int *b ) { int t = *a; *a = *b; *b = t; }
Instead of swapping the contents of a and b, we swap the contents of the objects that a and b point to. This crops up all the time - think about the scanf function, and how you have to use the & operator on scalar arguments.
Tracking dynamically allocated memory
The dynamic memory allocation functions malloc, calloc, and realloc all return pointers to dynamic memory buffers; there's no variable associated with that memory as such.
char *buffer = malloc( sizeof *buffer * some_length );
A pointer is the only way to track that memory.

Copy of address in C?

I know that this code:
void incVar(int i){
i++;
}
We know this will create a copy of the integer and then increase that value, but not the actual value.
By nature: Methods in C create copies of parameters in their Stack Frame and not the original variable.
But:
void incVar(int *i){
(*i)++;
}
Is supposed to increase the actual value of the integer by the pointer dereference.
But then, why doesn't C just create a copy of the pointer *i instead? If this is the normal behavior with regular integers, then why doesn't the same thing happen with pointers?
It is the same with pointers. All variables in C are passed by value, even pointers.
You copy the address stored in the pointer outside the function, into its parameter.
But you can use that address to reference a variable which can be allocated anywhere. So in the following code:
int j = 0;
incVar(&j);
incVar receives by-copy the address of j. But it can use that address to read or modify j (in)directly.
In fact the same thing as with values happens with pointers. Just make sure to understand the syntax correctly. You are not passing the integer *i by copy to incVar, but you are passing the pointer i of type int* by copy. No matter how often you copy the pointer to an address, it always points to the same address. So i in your second incVar example points to the integer the caller took the address of. So by derefencing the copy of the pointer (in (*i)++), you are acessing the integer of the caller.
Its better to see int *i; as a variable named i of type pointer-to-int, instead of a pointer named *i.
In your example:
void incVar(int *i) {
(*i)++;
}
We probably use it as such in the main function:
int a = 5;
incVar(&a); //After this line, a is now 6.
What happens in incVar(..) is this:
A variable i is created, of type pointer-to-int.
It holds a copy of the value of &a.
Although i is a copy, its value is the same as that of the value of &a, and it still points to the same integer a.
As a result, by de-referencing i, I refer to the integer a.
Increment the integer a, which obviously is at the address pointed to by i.

Declare and initialize pointer concisely (i. e. pointer to int)

Given pointers to char, one can do the following:
char *s = "data";
As far as I understand, a pointer variable is declared here, memory is allocated for both variable and data, the latter is filled with data\0 and the variable in question is set to point to the first byte of it (i. e. variable contains an address that can be dereferenced). That's short and compact.
Given pointers to int, for example, one can do this:
int *i;
*i = 42;
or that:
int i = 42;
foo(&i); // prefix every time to get a pointer
bar(&i);
baz(&i);
or that:
int i = 42;
int *p = &i;
That's somewhat tautological. It's small and tolerable with one usage of a single variable. It's not with multiple uses of several variables, though, producing code clutter.
Are there any ways to write the same thing dry and concisely? What are they?
Are there any broader-scope approaches to programming, that allow to avoid the issue entirely? May be I should not use pointers at all (joke) or something?
String literals are a corner case : they trigger the creation of the literal in static memory, and its access as a char array. Note that the following doesn't compile, despite 42 being an int literal, because it is not implicitly allocated :
int *p = &42;
In all other cases, you are responsible of allocating the pointed object, be it in automatic or dynamic memory.
int i = 42;
int *p = &i;
Here i is an automatic variable, and p points to it.
int * i;
*i = 42;
You just invoked Undefined Behaviour. i has not been initialized, and is therefore pointing somewhere at random in memory. Then you assigned 42 to this random location, with unpredictable consequences. Bad.
int *i = malloc(sizeof *i);
Here i is initialized to point to a dynamically-allocated block of memory. Don't forget to free(i) once you're done with it.
int i = 42, *p = &i;
And here is how you create an automatic variable and a pointer to it as a one-liner. i is the variable, p points to it.
Edit : seems like you really want that variable to be implicitly and anonymously allocated. Well, here's how you can do it :
int *p = &(int){42};
This thingy is a compound literal. They are anonymous instances with automatic storage duration (or static at file scope), and only exist in C90 and further (but not C++ !). As opposed to string literals, compound literals are mutable, i.e you can modify *p.
Edit 2 : Adding this solution inspired from another answer (which unfortunately provided a wrong explanation) for completeness :
int i[] = {42};
This will allocate a one-element mutable array with automatic storage duration. The name of the array, while not a pointer itself, will decay to a pointer as needed.
Note however that sizeof i will return the "wrong" result, that is the actual size of the array (1 * sizeof(int)) instead of the size of a pointer (sizeof(int*)). That should however rarely be an issue.
int i=42;
int *ptr = &i;
this is equivalent to writing
int i=42;
int *ptr;
ptr=&i;
Tough this is definitely confusing, but during function calls its quite useful as:
void function1()
{
int i=42;
function2(&i);
}
function2(int *ptr)
{
printf("%d",*ptr); //outputs 42
}
here, we can easily use this confusing notation to declare and initialize the pointer during function calls. We don't need to declare pointer globally, and the initialize it during function calls. We have a notation to do both at same time.
int *ptr; //declares the pointer but does not initialize it
//so, ptr points to some random memory location
*ptr=42; //you gave a value to this random memory location
Though this will compile, but it will invoke undefined behaviour as you actually never initialized the pointer.
Also,
char *ptr;
char str[6]="hello";
ptr=str;
EDIT: as pointed in the comments, these two cases are not equivalent.
But pointer points to "hello" in both cases. This example is written just to show that we can initialize pointers in both these ways (to point to hello), but definitely both are different in many aspects.
char *ptr;
ptr="hello";
As, name of string, str is actually a pointer to the 0th element of string, i.e. 'h'.
The same goes with any array arr[], where arr contains the address of 0th element.
you can also think it as array , int i[1]={42} where i is a pointer to int
int * i;
*i = 42;
will invoke undefined behavior. You are modifying an unknown memory location. You need to initialize pointer i first.
int i = 42;
int *p = &i;
is the correct way. Now p is pointing to i and you can modify the variable pointed to by p.
Are there any ways to write the same thing dry and concisely?
No. As there is no pass by reference in C you have to use pointers when you want to modify the passed variable in a function.
Are there any broader-scope approaches to programming, that allow to avoid the issue entirely? May be I should not use pointers at all (joke) or something?
If you are learning C then you can't avoid pointers and you should learn to use it properly.

Resources