C, two kinds of functions - c

I always see two kinds of functions like the following:
void Function_1(
int** buff
)
{
int* retNb = null;
retNb = (int*) malloc(42 * sizeof(int));
*buff = retNb;
}
void Function_2(
int* retNb
)
{
retNb = (int*) malloc(42 * sizeof(int));
}
What is the difference between function_1 and function_2 ? What are their use case ?

A really big difference, they're really different - by ANY means.
Let's keep it simple:
void Function_1(int** buff)
Parameter in function 1 is a pointer to a pointer to an int named buff and what this function does is the following:
int* retNb = null;
Declaring an int pointer called retNb, the assignment to NULL here is really not necessary, though, because next line is the following:
retNb = (int*) malloc(42 * sizeof(int));
retNb is called to get the value returned from malloc. malloc allocated 42*sizeof(int) spot in memory and returned it to retNb and now it can be treated as a simple array with 42 integers and can be accessed with square brackets [] as retNb[i].
*buff = retNb;
in pointers * is the way to get to the content of the address in the variable (variable == pointer in this case) so when using *buff when buff is **buff (a pointer to a pointer) you're actually asking for the pointer buff points to. Let's say we have the code:
int** myPointerToPointer = NULL;
int* myPointer = malloc(sizeof(int));
*myPointer = 4; //or myPointer[0] = 4;
printf("%d\n", *myPointer);
myPointerToPointer = &myPointer;
printf("%d\n", *(*myPointerToPointer));
printf("%d\n", &myPointer);
printf("%d\n", *myPointerToPointer);
then the output would be:
4
4
SOME_ADDRESS
SAME_ADDRESS
because the first printing is the value of myPointer (4) and the second is the value of the value of myPointerToPointer which value is myPointer which value is 4 :P
Third and fourth outputs are the same two because the address of myPointer is actually where myPointerToPointer is pointing to.
About the second function:
void Function_2(int* retNb)
It gets an int pointer - not a pointer to a pointer - just a pointer - means it contains an address of an integer variable that can be accessed with the opeartor *.
retNb = (int*) malloc(42 * sizeof(int));
this line is assigning dynamic memory (again 42 times sizeof(int)) and now can be treated as a regular int array with 42 spots - BUT that's the only thing it does, it won't have anything point to it, just assign memory and that's it.
Hope you understand :P

In function two u are have a pointer to an array of 42 ints.
int function 1 you set buff to point to this array.

Related

What does *p mean when **p is already declared

Code
short **p = (short **)malloc(sizeof(short *));
*p = malloc(sizeof(short));
**p = 10;
printf("**p = %d", **p);
Output
**p = 10
In this code, a multiple pointer **p is declared and *p is used without any declaration(maybe it's by **p).
What does *p mean in my case? Sorry for very simple question.
I saw C standard and stack overflow, but I couldn't find out something.
For any array or pointer p and index i, the expression p[i] is exactly equal to *(p + i) (where * is the unary dereference operator, the result of it on a pointer is the value that the pointer is pointing to).
So if we have p[0] that's then exactly equal to *(p + 0), which is equal to *(p) which is equal to *p. Going backwards from that, *p is equal to p[0].
So
*p = malloc(sizeof(short));
is equal to
p[0] = malloc(sizeof(short));
And
**p = 10;
is equal to
p[0][0] = 10;
(**p is equal to *(*(p + 0) + 0) which is equal to *(p[0] + 0) which is then equal to p[0][0])
It's important to note that the asterisk * can mean different things in different contexts.
It can be used when declaring a variable, and then it means "declare as pointer":
int *p; // Declare p as a pointer to an int value
It can be used to dereference a pointer, to get the value the pointer is pointing to:
*p = 0; // Equal to p[0] = 0
And it can be used as the multiplication operator:
r = a * b; // Multiply the values in a and b, store the resulting value in r
short **p = (short **)malloc(sizeof(short *));
This line declares a pointer to a pointer p. Additionally the value of p is set to the return value from malloc. It is equivalent to
short **p;
p = (short **)malloc(sizeof(short *));
The second line
*p = malloc(sizeof(short));
Here *p is the value of p. *p is of type pointer. *p is set to the return value of malloc. It is equivalent to
p[0] = malloc(sizeof(short));
The third line
**p = 10;
**p is the value of the value of p. It is of type short. It is equivalent to
p[0][0] = 10
In effect what the code above does is to allocate a 2D array of short, then allocate memory for the first row, and then set the element p[0][0] to 10.
As a general comment on your code, you should not use typecast in malloc. See Do I cast the result of malloc?
What does *p mean when **p is already declared?
short **p = (short **)malloc(sizeof(short *));
(better written as)
short **p = malloc (sizeof *p);
Declares the pointer-to-pointer-to short p and allocates storage for a signle pointer with malloc and assigns the beginning address for that block of memory to p. See: In C, there is no need to cast the return of malloc, it is unnecessary. See: Do I cast the result of malloc?
*p = malloc(sizeof(short));
(equivalent to)
p[0] = malloc (sizeof *p[0]);
Allocates storage for a single short and assigns the starting address for that block of memory to p[0].
**p = 10;
(equivalent to)
*p[0] = 10;
(or)
p[0][0] = 10;
Assigns the value 10 to the dereference pointer *p[0] (or **p or p[0][0]) updating the value at that memory address to 10.
printf("**p = %d", **p);
Prints the value stored in the block of memory pointed to by p[0] (the value accessed by dereferencing the pointer as *p[0] or **p)
The way to keep this straight in your head, is p is a single pointer of type pointer-to-pointer-to short. There are 2-level of indirection (e.g. pointer-to-pointer). To remove one level of indirection, you use the unary * operator, e.g.
*p /* has type pointer-to short */
or the [..] also acts as a dereference such that:
p[0] /* also has type pointer-to short */
You still have a pointer-to so you must remove one more level of indirection to refernce the value stored at the memory location pointed to by the pointer. (e.g. the pointer holds the address where the short is stored as its value). So you need:
**p /* has type short */
and
*p[0] /* also has type short */
as would
p[0][0] /* also has type short */
The other piece to keep straight is the type controls pointer-arithmetic. So p++ adds 8-bytes to the pointer-to-ponter address so it now points to the next pointer. If you do short *q = (*p)++; (or short *q = p[0]++, adds 2-bytes to the address for the pointer-to-short, soqnow points to the nextshortin the block of memory beginning at*p(orp[0]`). (there is no 2nd short because you only allocated 1 -- but you get the point)
Let me know if you have further questions.
Let me put it in different way,
consider an example,
int x;
int *y = &x;
int **z = &y;
x = 10;
Which simplifies to this,
Note: Only for illustration purpose I have chosen address of x,y,z as 0x1000,0x2000,0x3000 respectively.
What does *p mean in my case?
In short the snippetshort **p = (short **)malloc(sizeof(short *)); is dynamically allocating a pointer to a pointer of type short i.e same asy in my example.

Understanding Pointer to Pointer Logic in C

I came across this code and was a bit confused on exactly what's going on here:
int **p;
p = malloc(sizeof(int *));
*p = malloc(sizeof(int));
**p = 10;
printf("%d\n",**p);
First of, p is a pointer to a pointer but it doesn't point to anything else, so why would we have to malloc twice here? Also in the first malloc call, why does one not need to have two pointer values around the p:
for instance:
**p = malloc(sizeof(int *));
instead of :
p = malloc(sizeof(int *));
I understand that the next line deference's the pointer and stores the value 10 in it, and then prints it. However I don't really get the previous lines, or at least why they're done in that frame of mind.
I'm used to seeing double pointers in this mindset:
int main(void) {
int *ptr;
int **ptr_ptr;
ptr = malloc(sizeof(int));
*ptr = 5;
ptr_ptr = &ptr;
printf("%d\n",**ptr_ptr); /*prints 5*/
free(ptr);
return 0;
}
As the double pointer actually points to something here. Any help with the first bit of code would be much appreciated.
As int **p is a pointer to pointer, it will hold the location or address of an int* type of pointer. But one must first allocate enough memory for the int* which will be stored at the location pointed by p. This line does this job, it initializes p:
p = malloc(sizeof(int *));
Now, that int*'s location is known, one must allocate memory to store an acutal int at the memory pointed by *p which is our int* pointer. So another malloc() call is needed to initialize the int* type pointer.
*p = malloc(sizeof(int));
When all of it is done, an integer can be assigned to **p, which is the int pointed by *p:
**p = 10;
After the two mallocs, the variable p contains a pointer to a malloc-allocated pointer, which in turn contains a pointer to a malloc-allocated integer:
+---+ +---+ +----+
p: | ----> | ----> | 10 |
+---+ +---+ +----+

Array Pointers vs Regular Pointers in C

I am a total beginner to C so please, work with my ignorance. Why does a normal pointer
int* ptr = &a; has two spaces in memory (one for the pointer variable and one for the value it points to) and an array pointer int a[] = {5}; only has one memory space (if I print out
printf("\n%p\n", a) I get the same address as if I printed out: printf("\n%p\n", &a).
The question is, shouldn't there be a memory space for the pointer variable a and one for its value which points to the first array element? It does it with the regular pointer int* ptr = &a;
It's a little unclear from your question (and assuming no compiler optimization), but if you first declare a variable and then a pointer to that variable,
int a = 4;
int *p = &a;
then you have two different variables, it makes sense that there are two memory slots. You might change p to point to something else, and still want to refer to a later
int a = 4;
int b = 5;
int *p = &a; // p points to a
// ...
p = &b; // now p points to b
a = 6; // but you can still use a
The array declaration just allocates memory on the stack. If you wanted to do the same with a pointer, on the heap, you would use something like malloc or calloc (or new in c++)
int *p = (int*)malloc(1 * sizeof(int));
*p = 4;
but of course remember to free it later (delete in c++)
free(p);
p = 0;
The main misunderstanding here is that &a return not pointer to pointer as it expected that's because in C language there some difference between [] and * (Explanation here: Difference between [] and *)
If you try to &a if a was an pointer (e.g. int *a) then you obtain a new memory place but when your use a static array (i.e. int a[]) then it return address of the first array element. I'll also try to clarify this by mean of the next code block.
#include <stdio.h>
int main(int argc, char *argv[])
{
// for cycles
int k;
printf("That is a pointer case:\n");
// Allocate memory for 4 bytes (one int is four bytes on x86 platform,
// can be differ for microcontroller e.g.)
int c = 0xDEADBEEF;
unsigned char *b = (unsigned char*) &c;
printf("Value c: %p\n", c);
printf("Pointer to c: %p\n", &c);
printf("Pointer b (eq. to c): %p\n", b);
// Reverse order (little-endian in case of x86)
for (k = 0; k < 4; k++)
printf("b[%d] = 0x%02X\n", k, b[k]);
// MAIN DIFFERENCE HERE: (see below)
unsigned char **p_b = &b;
// And now if we use & one more we obtain pointer to the pointer
// 0xDEADBEEF <-- b <-- &p_b
// This pointer different then b itself
printf("Pointer to the pointer b: %p\n", p_b);
printf("\nOther case, now we use array that defined by []:\n");
int a[] = {5,1};
int *ptr = &a;
// 'a' is array but physically it also pointer to location
// logically it's treat differ other then real pointer
printf("'a' is array: %x\n", a);
// MAIN DIFFERENCE HERE: we obtain not a pointer to pointer
printf("Pointer to 'a' result also 'a'%x\n", &a);
printf("Same as 'a': %x\n", ptr);
printf("Access to memory that 'a' pointes to: \n%x\n", *a);
return 0;
}
This is very simple. In first case,
int* ptr = &a;
you have one variable a already declared and hence present in memory. Now you declare another variable ptr (to hold the address, in C variables which hold address of another variable are called pointers), which again requires memory in the same way as a required.
In second case,
int a[] = {5};
You just declare one variable (which will hold a collection of ints), hence memory is allocated accordingly for a[].
In this expression, int* p = &a; p has only one memory location, of the WORD size of your CPU, most probably, and it is to store the address (memory location) of another variable.
When you do *p you are dereferencing p, which means you are getting the value of what p points to. In this particular case that would be the value of a. a has its own location in memory, and p only points to it, but does not itself store as content.
When you have an array, like int a[] = {5};, you have a series (or one) of memory locations, and they are filled with values. These are actual locations.
Arrays in C can decay to a pointer, so when you printf like you did with your array, you get the same address, whether you do a or &a. This is because of array to pointer decay.
a is still the same location, and is only that location. &a actually returns a pointer to a, but that pointer sits else where in memory. If you did int* b = &a; then b here would not have the same location as a, however, it would point to a.
ptr is a variable containing a memory address. You can assign various memory addresses to ptr. a is a constant representing a fixed memory address of the first element of the array. As such you can do:
ptr = a;
but not
a = ptr;
Pointers point to an area in memory. Pointers to int point to an area large enough to hold a value of int type.
If you have an array of int and make a pointer point to the array first element
int array[42];
int *p = array;
the pointer still points to a space wide enough for an int.
On the other hand, if you make a different pointer point to the whole array, this new pointer points to a larger area that starts at the same address
int (*q)[42]; // q is a pointer to an array of 42 ints
q = &array;
the address of both p and q is the same, but they point to differently sized areas.

Not able to access array elements?

i have this array where i am trying to access its elements by incrementing ptr, as suggested here Trying to find different methods of accessing array elements?...i must be doing something stupid...please help me!
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
char *p1 = "Cnversions";
char *p2 = "Divided";
char *p3 = "Plain";
char *p4 = "Solid";
char *arr[3];
arr[0] = p1;
arr[1] = p2;
arr[2] = p3;
arr[3] = p4;
for(i=0;i<=3;i++)
{
printf("string at arr[%d] is: %s\n",i,*arr);
arr++;
}
return 0;
}
An array like arr is located at a specific spot in memory, so it makes no sense to increment arr (what does it mean to increment an array?)
Instead, you will need to create a pointer to the start of the array and increment the pointer:
char **ptr = arr;
for(i=0; i<4; i++) {
printf("arr[%d] = %s\n", i, *ptr);
ptr++;
}
(Note also that you need to make arr four elements big, i.e. char *arr[4], to accommodate the four string pointers you put in it.)
Remember that although we tend to think of double pointers as arrays, all the compiler sees them as are pointers. When you increment a pointer, it adds a value to the address of the pointer equal to the size of the data type it's pointing at. For example:
int *p;
p = (int *) malloc(sizeof(int));
p is pointing to an int, so the size of p's pointed data is (typically) 4 bytes. This means when you increment p, it will be pointing at a location 4 bytes greater than where it was before.
The type of arr is a char**, meaning that it's a pointer to a pointer to a char. Pointers on most machines these days are 8 bytes. So when you incrementing arr, you are effectively telling the computer to set arr to point to an address 8 bytes higher than what it was at before. In the case of arr, this is an illegal address, so you'll get some kind of crash.

c language. Return type of a function

?? fun()
{
int a[3]={3,3,4};
return &a;
}
what could be the compatible return type. Here the pointer is pointing to the array of 3 integers not just the pointer which points to integer array.
Aim is to return a pointer to array of 3 integers.
First, you really should not return the address of a local variable. When the function exits, the array a will get destroyed.
As for your question, the type of &a is int (*)[].
Don't do this.
You are returning a pointer to a local variable. When the function returns, that pointer points to a location that's no longer valid, so this exercise is pointless.
The return type would have been int (*)[3] though, but when you use that as a return type of a function, the prototype would be int (*fun(void))[3] (ugh, eew)
However
If a was static, you could do
int (*fun(void))[3]
{
static int a[3]={3,3,4};
return &a;
}
It's more common to return a pointer to the first element in an array - though you'll have to "know" in the caller that you can access 3 and only 3 elements of that pointer.
int *fun(void)
{
static int a[3]={3,3,4};
return &a[0]; // or just return a;
}
Since a is static in these cases, you'll have to worry about reentrancy
2 more common ways of achieving the same:
Pass in the array through the parameters and allocate it in the caller:
void fun(int *a)
{
a[0] = 3;
a[1] = 3;
a[2] = 4;
}
Call it like:
int a[3];
fun(a);
Dynamically allocate the memory:
int *fun(void)
{
int *a = malloc(3*sizeof *a);
if(a) {
a[0] = 3;
a[1] = 3;
a[2] = 4;
}
return a;
}
Call it like:
int *a;
a = fun();
if(a) {
///use a
free(a); // remember to free it when done
} else {
//out of memory
}
The return type would not be an int* or int** as others have suggested. The return type would be a pointer to an array. For example:
// we'll use a typedef so we can keep our sanity:
typedef int(*int3arrayptr)[3];
int3arrayptr fun()
{
int a[3]={3,3,4};
return &a;
}
While you can return a pointer to a local variable, you cannot use such a pointer after the function returns, so you cannot use the return value of fun().
The type would be int**
But your code is wrong because your table is on the stack.
Returning the pointer of an element in the stack make the reference pointing in nowhere when returning from the function.
Don't make the mistake. As soon as fun() loses scope, so does all it's local variables.
The address of a local variable cannot be returned from a function. Local variables are placed in the stack
a is a local variable. Don't return a pointer to it.
Back to the point. This is how you define a pointer-to-array-of-size-3 type in C:
int a[3] = { 1, 2, 3 };
typedef int (*p_arr_3)[3];
p_arr_3 fun() { return &a; }
Everyone else has already told you why you shouldn't do this as it is written, but here are the types you are interested in.
Given a declaration int a[3], the type of the expression &a is int (*)[3] (not int **), or "pointer to 3-element array of int", such as
void f()
{
int a[3] = {1,2,3};
int (*aptr)[3] = &a;
...
}
and the signature for a function returning that type would be int (*fun())[3] {...}.
One other option nos didn't show is this:
int (*fun())[3]
{
int (*aptr)[3] = malloc(sizeof *aptr);
if (aptr)
{
(*aptr)[0] = 1; // array pointer must be deferenced before applying
(*aptr)[1] = 2; // the subscript.
(*aptr)[2] = 3;
}
return aptr;
}
although this isn't terribly useful; you don't normally see allocations of single, fixed-size arrays like this. Somewhat more useful is allocating an array of those arrays:
int (*fun(size_t count))[3]
{
int (*aptr)[3] = malloc(sizeof *aptr * count);
if (aptr)
{
size_t i;
for (i = 0; i < count; i++)
{
aptr[i][0] = 1; // aptr[i] implicitly dereferences aptr, so
aptr[i][1] = 2; // there's no need for an explicit dereference
aptr[i][2] = 3; // here.
}
}
return aptr;
}
Even so, if somebody needs to allocate a fixed-size array type, they usually hide it behind a typedef:
typedef int fixedSizeRecord[SOME_SIZE];
...
fixedSizeRecord *fun(size_t count)
{
fixedSizeRecord *aptr = malloc(sizeof *aptr * count);
if (aptr)
{
// initialize contents as necessary
for (size_t i = 0; i < count; i++)
for (j = 0; j < sizeof *aptr / sizeof *aptr[0]; j++)
aptr[i][j] = ...;
}
return aptr;
}
Abstraction is a good thing.
I've put up several iterations of this table before; you might find it handy.
Declaration: T a[N];
Expression Type Decays To Value
---------- ---- --------- -----
a T [N] T * Address of first element in a
&a T (*)[N] n/a Address of a (same value as above,
but different type)
*a T n/a Same as a[0]
a[i] T n/a Value at index i
&a[i] T * n/a Address of value at index i
sizeof a size_t Total number of bytes in a
(N * sizeof T)
sizeof a /
sizeof *a size_t n/a Number of elements in a (N)
Declaration: T a[N][M];
Expression Type Decays To Value
---------- ---- --------- -----
a T [N][M] T (*)[M] Address of first element in a[0]
&a T (*)[N][M] n/a Address of a (same value as above,
but different type)
*a T [M] T * Same as a[0]
a[i] T [M] T * Address of first element in array
at index i
&a[i] T (*)[M] n/a Address of array at index i (same
value as above, but different
type)
*a[i] T n/a Same as a[i][0]
a[i][j] T n/a Value at a[i][j]
&a[i][j] T * n/a Address of value at index i,j
sizeof a size_t n/a Total number of bytes in a
(N * M * sizeof T)
sizeof a /
sizeof *a size_t n/a Number of subarrays in a (N)
sizeof a[i] size_t n/a Total number of bytes in a[i]
(M * sizeof T)
sizeof a[i] /
sizeof *a[i] size_t n/a Number of elements in a[i] (M)
If you want to return a pointer to an array, don't return the address of local variables. What you are returning here would be int**. What you want to do is allocate a new array of int, and return int*. What you want is probably something like:
int* fun()
{
int* a = malloc(sizeof(int) * 3);
a[0] = 3;
a[1] = 3;
a[2] = 4;
return a;
}
You then need to make sure to free the allocated array later.
Your function would have a return type of int * and you would call it like this:
int *array=fun();
printf("%d\n",array[0]); //print the first value in the array
Although! Keep in mind that this function is returning a reference to a locally created variable. There is no guarantee that the value in memory will be the same between inside and after the function call. You probably want to do something more like this:
int *more_fun(){
int *a=malloc(sizeof(int)*3);
a[0]=3;
a[1]=3;
a[2]=4;
return a;
}
Call it like:
int *array=more_fun();
printf("%d\n",array[0]); //print the first value in the array
But when you're done, make sure to free(array) so you don't leak any memory.
If you were to return a, the return type would be int *. I'm not entirely sure what &a means in this case, and my handy reference tells me that the only operation that can be applied to an array is sizeof, and I don't have the Standard handy. It may be flagged as illegal, or it may just return the value of a. The only thing a denotes is the array, and the only thing like a pointer to an array is a pointer to its first element. There is no address of the address.
In C, it's hard to pass around an array, since arrays decay to pointers on the slightest provocation. If you need to pass around an actual array, it's easiest to embed it in a struct. A struct containing int a[3]; can be passed around as a regular value.
I assume that you were just giving an example, because you're returning a reference to a local variable leads to all sorts of bad things. In most implementations, that memory will be used for other things with the next function call, which means that changing a value will stomp on who-knows-what, and referencing one will get who-knows-what.

Resources