When to use * in pointer assignment? [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
As I'm learning C I often see pointers.
I get that a pointer is holding the hexadecimal value of a distinct location in memory. So a pointer is nothing other than e.g.:0x7fff5fbff85c
Every pointer is also of a distinct type.
int var = 10;
int *ptr = &var;
Ptr here points to the location of var. To get the value of var I have to dereference the pointer with *ptr.
Like
printf("Var = %d", *ptr);
would print `Var = 10;
However If I do a non inline declaration of a pointer like:
int var = 10;
int *ptr;
ptr = &var;
I don't have to use the * in the third line when I'm actually assigning the memory adress to the pointer.
But when I got a function that takes a pointer:
int var = 10;
void assignPointer(int *ptr) {
*ptr = 10;
}
Oh, wait! As I'm writing this I recognized that there are two different assignments for pointers:
*ptr = 10;
and
ptr = &var;
What is the difference? Am I in the first case first dereferencing the pointer, assigning 10 to the location that its holding?
And in the second case I'am assigning the actual location to the pointer.
I'm a little bit confused when to use the * and when not to in terms of assignment.
And if I'm working with arrays, why do I need pointers at all?
int array[];
"array" here is already holding the hexadecimal memory location. Doesn't that make it a pointer? So If I wanted to assign something to array wouldn't I write:
*array = [10, 2];
First I'm dereferencing, then I'm assigning.
I'm lost :(
EDIT: Maybe it's a bit unclear.
I don't know when you have to use a * when you are working with pointers an when not.
Everything that is carrying a hexadecimal is a pointer right?
The variable name of an array is carrying it's hexadecimal memory location. So why isn't it a pointer?
EDIT2: Thank you people you helped me a lot!

I don't know when you have to use a * when you are working with pointers an when not. Everything that is carrying a hexadecimal is a pointer right? The variable name of an array is carrying it's hexadecimal memory location. So why isn't it a pointer?
Last thing first - the name of an array is not a pointer; it does not store an address anywhere. When you define an array, it will be laid out more or less like the following:
+---+
arr: | | arr[0] Increasing address
+---+ |
| | arr[1] |
+---+ |
... |
+---+ |
| | arr[n-1] V
+---+
There is no storage set aside for an object arr separate from the array elements arr[0] through arr[n-1]. C does not store any metadata such as length or starting address as part of the array object.
Instead, there is a rule that says if an array expression appears in your code and that expression is not the operand of the sizeof or unary & operators, it will be converted ("decay") to a pointer expression, and the value of the pointer expression will be the address of the first element of the array.
So given the declaration
T arr[N]; // for any type T
then the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
arr T [N] T * Address of first element
&arr T (*)[N] n/a Address of array (same value
as above
*arr T n/a Value of arr[0]
arr[i] T n/a Value of i'th element
&arr[i] T * n/a Address of i'th element
sizeof arr size_t Number of storage units (bytes)
taken up by arr
The expressions arr, &arr, and &arr[0] all yield the same value (the address of the first element of the array is the same as the address of the array), but their types aren't all the same; arr and &arr[0] have type T *, while &arr has type T (*)[N] (pointer to N-element array of T).
Everything that is carrying a hexadecimal is a pointer right?
Hexadecimal is just a particular representation of binary data; it's not a type in and of itself. And not everything that can be written or displayed in hex is a pointer. I can assign the value 0xDEADBEEF to any 32-bit integer type; that doesn't make it a pointer.
The exact representation of a pointer can vary between architectures; it can even vary between different pointer types on the same architecture. For a flat memory model (like any modern desktop architecture) it will be a simple integral value. For a segmented architecture (like the old 8086/DOS days) it could be a pair of values for page # and offset.
A pointer value may not be as wide as the type used to store it. For example, the old Motorola 68000 only had 24 address lines, so any pointer value would only be 24 bits wide. However, to make life easier, most compilers used 32-bit types to represent pointers, leaving the upper 8 bits unused (powers of 2 are convenient).
I don't know when you have to use a * when you are working with pointers an when not.
Pretty simple - when you want to refer to the pointed-to entity, use the *; when you want to refer to the pointer itself, leave it off.
Another way to look at it - the expression *ptr is equivalent to the expression var, so any time you want to refer to the contents of var you would use *ptr.
A more concrete example might help. Assume the following:
void bar( T *p )
{
*p = new_value(); // write new value to *p
}
void foo( void )
{
T var;
bar( &var ); // write a new value to var
}
In the example above, the following are true:
p == &var
*p == var
If I write something to *p, I'm actually updating var. If I write something to p, I'm setting it to point to something other than var.
This code above is actually the primary reason why pointers exist in the first place. In C, all function arguments are passed by value; that is, the formal parameter in the function definition is a separate object from the actual parameter in the function call. Any updates to the formal parameter are not reflected in the actual parameter. If we change the code as follows:
void bar( T p )
{
p = new_value(); // write new value to p
}
void foo( void )
{
T var;
bar( var ); // var is not updated
}
The value of p is changed, but since p is a different object in memory from var, the value in var remains unchanged. The only way for a function to update the actual parameter is through a pointer.
So, if you want to update the thing p points to, write to *p. If you want to set p to point to a different object, write to p:
int x = 0, y = 1;
int *p = &x; // p initially points to x
printf( "&x = %p, x = %d, p = %p, *p = %d\n", (void *) &x, x, (void *) p, *p );
*p = 3;
printf( "&x = %p, x = %d, p = %p, *p = %d\n", (void *) &x, x, (void *) p, *p );
p = y; // set p to point to y
printf( "&y = %p, y = %d, p = %p, *p = %d\n", (void *) &y, y, (void *) p, *p );
At this point you're probably asking, "why do I use the asterisk in int *p = &x and not in p = y?" In the first case, we're declaring p as a pointer and initializing it in the same operation, and the * is required by the declaration syntax. In that case, we're writing to p, not *p. It would be equivalent to writing
int *p;
p = &x;
Also note that in a declaration the * is bound to the variable name, not the type specifier; it's parsed as int (*p);.
C declarations are based on the types of expressions, not objects. If p is a pointer to an int, and we want to refer to the pointed-to value, we use the * operator to dereference it, like so:
x = *p;
The type of the expression *p is int, so the declaration is written as
int *p;

C syntax is weird like this. When you declare a variable, the * is only there to indicate the pointer type. It does not actually dereference anything. Thus,
int *foo = &bar;
is as if you wrote
int *foo;
foo = &bar;

Pointers are declared similar to regular variables.The asterisk character precede the name of the pointer during declaration to distinguish it as a pointer.At declaration you are not de-referencing,e.g.:
int a = 0;
int *p = &a // here the pointer of type int is declared and assigned the address of the variable a
After the declaration statement,to assign the pointer an address or value,you use it's name without the asterisk character,e.g:
int a;
int *p;
p = &a;
To assign the target of the pointer a value,you dereference it by preceding the pointer name with *:
int a = 0;
int *p;
p = &a;
*p = 1;

Dereferenced pointer is the memory it points to. Just don't confuse declaring the pointer and using it.
It may be a bit easier to understand if you write * in declaration near the type:
int* p;
In
int some_int = 10;
int* p = &some_int; // the same as int *p; p = &some_int;
*p = 20; // actually does some_int = 20;

You are pretty much correct.
Am I in the first case first dereferencing the pointer, assigning 10 to the location that its holding? And in the second case I'am assigning the actual location to the pointer.
Exactly. These are two logically different actions as you see.
"array" here is already holding the hexadecimal memory location. Doesn't that make it a pointer?
And you got the grasp of it as well here. For the sake of your understanding I would say that arrays are pointers. However in reality it is not that simple -- arrays only decay into pointers in most circumstances. If you are really into that matter, you can find a couple of great posts here.
But, since it is only a pointer, you can't "assign to array". How to handle an array in pointer context is usually explained in a pretty good way in any C book under the "Strings" section.

You are right about the difference between assignment and dereferencing.
What you need to understand is that your array variable is a pointer to the first element of your continuous memory zone
So you can access the first element by dereferencing the pointer :
*array = 10;
You can access the nth element by dereferencing a pointer to the nth element :
*(array + (n * sizeof(my_array_type)) ) = 10;
Where the address is the pointer to the first element plus the offset to the nth element (computed using the size of an element in this array times n).
You can also use the equivalent syntax the access the nth element :
array[n] = 10;

One of your examples isn't valid. *ptr = 10;. The reason is that 10 is a value but there is no memory assigned to it.
You can think of your examples as "assigning something to point at the address" or "the address of something is". So,
int *ptr is a pointer to the address of something. So ptr = &val; means ptr equals the address of val. Then you can say *ptr = 10; or val = 10; cause both *ptr and val are looking at the same memory location and, therefore, the same value. (Note I didn't say "pointing").

Related

what is the differece between *p=var and p = var in pointers? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I was learning pointers in c where i saw these examples and i become confused about pointers,
example1:
int i;
int a[5] = {1, 2, 3, 4, 5};
int *p = a; // same as int*p = &a[0]
for (i = 0; i < 5; i++)
{
printf("%d", *p);
p++;
}
output: 12345
example2:
int arr[2] = {1,2};
int *p;
p = arr;
int i ;
for(i = 0 ; i < 3 ; i++)
{
printf("%d",*p);
p++;
}
output:122
so what is the difference between *p=arr and p=arr in pointers ? and when i should use the first one and the second one ?
I think no answer here is actually addressing your confusion: *p vs p.
What you need to understand is that * has two completely different meanings depending on where it is used:
when it is used as part of the type specifier it denoted the pointer type. For instance when you declare a variable named p of type pointer to int: int* p. Here * is part of the type of the declaration and means pointer type.
when it is used in an expression it is the dereference operator. It's an unary operator accepting a pointer operand and it accesses the object found at that address. For instance in something like *p = 24.
You say what is the difference between *p = a and p = a but that is a wrong comparison for your example because *p from your doesn't stand on its own. Here is what I mean:
int * p = 24;
// ^~~~~ ^ ^----
// type | initializer
|
name of the variable
In the above:
int * is the type of the symbol declared.
p is the name of the variable declared
= 24 is the initializer for the variable
So you see talking about * p here makes no sense.
Talking about *p makes sense when * is the dereference operator. For instance:
int a = 11;
int b = 17;
int* p = &a; // declare the variable named p of type `int*`
// and assign `&a` (aka the address of a) to it
// p points to the object a
*p = 3; // assign 3 to the object found in memory at the address denoted by p
// this effectively changes `a` to 3
p = &b; // assign the address of b to p. p is now a pointer pointing to the object b
*p = 24; // assign 3 to the object found in memory at the address denoted by p
// this effectively changes `b` to 24
In C programming language,in some cases array name can decay to pointer to the first element in the array.Array name in your case is a in the first code snippet and arr in the second code snippet, can decays to pointer(address) to the array start in memory! So we can look at the array name somehow like an "alias" for the first element, &arr[0] !
Just to be clear, arrays are not pointers!
e.g. An array is a single, pre allocated chunk of contiguous elements (all of the same type), fixed in size and location, and A pointer is a place in memory that keeps address of another place inside.
so when we declare int *p = a; we are declaring a new pointer of type int* and initialize it to point to the first element in the array a. we also can do it like this (its the same):
int* p = &a[0]; //point to the first element in the array a
if you want to see on the screen, that this is correct, you can use the conversion format specifier %p inorder to print addresses:
see below:
printf("%p == %p \n",(void*)a,(void*)&a[0]);
you can read this web_page. they have a good examples.
for further reading about Relationship Between Arrays and Pointers please refare to this websites:
1. here
Here you define pointer p and initialize it. The * is used to show compiler that the p is the pointer and it does not dereference the p
int *p = a;
In this case you assign the pointer p with the reference to array (in this case to array arr as in the code in your question)
p = arr;
In the last statement you dereference the pointer p and the * is used to dereference the pointer
printf("%d",*p);
in the first example:
a points to the first integer in the array (the type of a is int *)
int *p = a; here we define a pointer p to points where a points to.
the same in second example:
we first define a pointer p and the we assign it to points where a points to.
A pointer is a variable which contains the address in memory of another variable. We can have a pointer to any variable type.
https://www.quora.com/What-is-the-difference-between-*p-**p-***p-in-pointers
The first example is an initialization - you are setting the value of p as you declare it. The second example is an assignment - you are setting the value of p as a standalone operation.
Both statements have the same effect in that they assign the address of the first element of a to p.
The unary * in a declaration simply means the thing being declared has pointer type - it’s not doing a dereference operation. The initializer is assigning a value to p, not to *p.

Confused on examples of basic functions in C [duplicate]

Is an array's name a pointer in C?
If not, what is the difference between an array's name and a pointer variable?
An array is an array and a pointer is a pointer, but in most cases array names are converted to pointers. A term often used is that they decay to pointers.
Here is an array:
int a[7];
a contains space for seven integers, and you can put a value in one of them with an assignment, like this:
a[3] = 9;
Here is a pointer:
int *p;
p doesn't contain any spaces for integers, but it can point to a space for an integer. We can, for example, set it to point to one of the places in the array a, such as the first one:
p = &a[0];
What can be confusing is that you can also write this:
p = a;
This does not copy the contents of the array a into the pointer p (whatever that would mean). Instead, the array name a is converted to a pointer to its first element. So that assignment does the same as the previous one.
Now you can use p in a similar way to an array:
p[3] = 17;
The reason that this works is that the array dereferencing operator in C, [ ], is defined in terms of pointers. x[y] means: start with the pointer x, step y elements forward after what the pointer points to, and then take whatever is there. Using pointer arithmetic syntax, x[y] can also be written as *(x+y).
For this to work with a normal array, such as our a, the name a in a[3] must first be converted to a pointer (to the first element in a). Then we step 3 elements forward, and take whatever is there. In other words: take the element at position 3 in the array. (Which is the fourth element in the array, since the first one is numbered 0.)
So, in summary, array names in a C program are (in most cases) converted to pointers. One exception is when we use the sizeof operator on an array. If a was converted to a pointer in this context, sizeof a would give the size of a pointer and not of the actual array, which would be rather useless, so in that case a means the array itself.
When an array is used as a value, its name represents the address of the first element.
When an array is not used as a value its name represents the whole array.
int arr[7];
/* arr used as value */
foo(arr);
int x = *(arr + 1); /* same as arr[1] */
/* arr not used as value */
size_t bytes = sizeof arr;
void *q = &arr; /* void pointers are compatible with pointers to any object */
If an expression of array type (such as the array name) appears in a larger expression and it isn't the operand of either the & or sizeof operators, then the type of the array expression is converted from "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element in the array.
In short, the array name is not a pointer, but in most contexts it is treated as though it were a pointer.
Edit
Answering the question in the comment:
If I use sizeof, do i count the size of only the elements of the array? Then the array “head” also takes up space with the information about length and a pointer (and this means that it takes more space, than a normal pointer would)?
When you create an array, the only space that's allocated is the space for the elements themselves; no storage is materialized for a separate pointer or any metadata. Given
char a[10];
what you get in memory is
+---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
+---+
| | a[9]
+---+
The expression a refers to the entire array, but there's no object a separate from the array elements themselves. Thus, sizeof a gives you the size (in bytes) of the entire array. The expression &a gives you the address of the array, which is the same as the address of the first element. The difference between &a and &a[0] is the type of the result1 - char (*)[10] in the first case and char * in the second.
Where things get weird is when you want to access individual elements - the expression a[i] is defined as the result of *(a + i) - given an address value a, offset i elements (not bytes) from that address and dereference the result.
The problem is that a isn't a pointer or an address - it's the entire array object. Thus, the rule in C that whenever the compiler sees an expression of array type (such as a, which has type char [10]) and that expression isn't the operand of the sizeof or unary & operators, the type of that expression is converted ("decays") to a pointer type (char *), and the value of the expression is the address of the first element of the array. Therefore, the expression a has the same type and value as the expression &a[0] (and by extension, the expression *a has the same type and value as the expression a[0]).
C was derived from an earlier language called B, and in B a was a separate pointer object from the array elements a[0], a[1], etc. Ritchie wanted to keep B's array semantics, but he didn't want to mess with storing the separate pointer object. So he got rid of it. Instead, the compiler will convert array expressions to pointer expressions during translation as necessary.
Remember that I said arrays don't store any metadata about their size. As soon as that array expression "decays" to a pointer, all you have is a pointer to a single element. That element may be the first of a sequence of elements, or it may be a single object. There's no way to know based on the pointer itself.
When you pass an array expression to a function, all the function receives is a pointer to the first element - it has no idea how big the array is (this is why the gets function was such a menace and was eventually removed from the library). For the function to know how many elements the array has, you must either use a sentinel value (such as the 0 terminator in C strings) or you must pass the number of elements as a separate parameter.
Which *may* affect how the address value is interpreted - depends on the machine.
An array declared like this
int a[10];
allocates memory for 10 ints. You can't modify a but you can do pointer arithmetic with a.
A pointer like this allocates memory for just the pointer p:
int *p;
It doesn't allocate any ints. You can modify it:
p = a;
and use array subscripts as you can with a:
p[2] = 5;
a[2] = 5; // same
*(p+2) = 5; // same effect
*(a+2) = 5; // same effect
The array name by itself yields a memory location, so you can treat the array name like a pointer:
int a[7];
a[0] = 1976;
a[1] = 1984;
printf("memory location of a: %p", a);
printf("value at memory location %p is %d", a, *a);
And other nifty stuff you can do to pointer (e.g. adding/substracting an offset), you can also do to an array:
printf("value at memory location %p is %d", a + 1, *(a + 1));
Language-wise, if C didn't expose the array as just some sort of "pointer"(pedantically it's just a memory location. It cannot point to arbitrary location in memory, nor can be controlled by the programmer). We always need to code this:
printf("value at memory location %p is %d", &a[1], a[1]);
I think this example sheds some light on the issue:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
int **b = &a;
printf("a == &a: %d\n", a == b);
return 0;
}
It compiles fine (with 2 warnings) in gcc 4.9.2, and prints the following:
a == &a: 1
oops :-)
So, the conclusion is no, the array is not a pointer, it is not stored in memory (not even read-only one) as a pointer, even though it looks like it is, since you can obtain its address with the & operator. But - oops - that operator does not work :-)), either way, you've been warned:
p.c: In function ‘main’:
pp.c:6:12: warning: initialization from incompatible pointer type
int **b = &a;
^
p.c:8:28: warning: comparison of distinct pointer types lacks a cast
printf("a == &a: %d\n", a == b);
C++ refuses any such attempts with errors in compile-time.
Edit:
This is what I meant to demonstrate:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
void *c = a;
void *b = &a;
void *d = &c;
printf("a == &a: %d\n", a == b);
printf("c == &c: %d\n", c == d);
return 0;
}
Even though c and a "point" to the same memory, you can obtain address of the c pointer, but you cannot obtain the address of the a pointer.
The following example provides a concrete difference between an array name and a pointer. Let say that you want to represent a 1D line with some given maximum dimension, you could do it either with an array or a pointer:
typedef struct {
int length;
int line_as_array[1000];
int* line_as_pointer;
} Line;
Now let's look at the behavior of the following code:
void do_something_with_line(Line line) {
line.line_as_pointer[0] = 0;
line.line_as_array[0] = 0;
}
void main() {
Line my_line;
my_line.length = 20;
my_line.line_as_pointer = (int*) calloc(my_line.length, sizeof(int));
my_line.line_as_pointer[0] = 10;
my_line.line_as_array[0] = 10;
do_something_with_line(my_line);
printf("%d %d\n", my_line.line_as_pointer[0], my_line.line_as_array[0]);
};
This code will output:
0 10
That is because in the function call to do_something_with_line the object was copied so:
The pointer line_as_pointer still contains the same address it was pointing to
The array line_as_array was copied to a new address which does not outlive the scope of the function
So while arrays are not given by values when you directly input them to functions, when you encapsulate them in structs they are given by value (i.e. copied) which outlines here a major difference in behavior compared to the implementation using pointers.
The array name behaves like a pointer and points to the first element of the array. Example:
int a[]={1,2,3};
printf("%p\n",a); //result is similar to 0x7fff6fe40bc0
printf("%p\n",&a[0]); //result is similar to 0x7fff6fe40bc0
Both the print statements will give exactly same output for a machine. In my system it gave:
0x7fff6fe40bc0

What does ** do in C language? [duplicate]

This question already has answers here:
Pointer to pointer clarification
(16 answers)
How do pointer-to-pointers work in C? (and when might you use them?)
(14 answers)
Closed 7 years ago.
I'm new to C with a good background in java and I'm trying to understand pointers and arrays.
I know that subscript operator[] is part of an array definition, so:
int numbers[] = {1,3,4,5};
would create a integer array, which would be represented in memory as 16 bytes, 4 lots of 4 bytes:
numbers[0] = 1, address 0061FF1C
numbers[1] = 3, address 0061FF20
numbers[2] = 4, address 0061FF24
numbers[3] = 5, address 0061FF28
However, when it comes to pointers my knowledge starts to break down, so if I was to create a pointer to the array numbers I would do the following:
int *pNumbers = &numbers[0];
which would look something like this:
And I'm guessing it would be of size 4 bytes?
However the ** I read as "pointer to a pointer" which makes no sense to me, why would anyone want a pointer to a pointer, surely if a->b->c then a->c would suffice? I know I'm missing something, and it must have something to do with arrays as argv can be of type char[ ] or char ** as seen bellow:
int main(int argc, char **argv){}
So:
what is this (**)?
what use does it have?
how is it represented in memory?
In C arguments are passed by values. For example if you have an integer varaible in main
int main( void )
{
int x = 10;
//...
and the following function
void f( int x )
{
x = 20;
printf( "x = %d\n", x );
}
then if you call the function in main like this
f( x );
then the parameter gets the value of variable x in main. However the parameter itself occupies a different extent in memory than the argument. So any changes of the parameter in the function do not influence to the original variable in main because these changes occur in different memory extent.
So how to change the varible in main in the function?
You need to pass a reference to the variable using pointers.
In this case the function declaration will look like
void f( int *px );
and the function definition will be
void f( int *px )
{
*px = 20;
printf( "*px = %d\n", *px );
}
In this case it is the memory extent occupied by the original variable x is changed because within the function we get access to this extent using the pointer
*px = 20;
Naturally the function must be called in main like
f( &x );
Take into account that the parameter itself that is the pointer px is as usual a local variable of the function. That is the function creates this variable and initializes it with the address of variable x.
Now let's assume that in main you declared a pointer for example the following way
int main( void )
{
int *px = malloc( sizeof( int ) );
//..
And the function defined like
void f( int *px )
{
px = malloc( sizeof( int ) );
printf( "px = %p\n", px );
}
As parameter px is a local variable assigning to it any value does not influence to the original pointer. The function changes a different extent of memory than the extent occupied by the original pointer px in main.
How to change the original pointer in the function?
Just pass it by reference!
For example
f( &px );
//...
void f( int **px )
{
*px = malloc( sizeof( int ) );
printf( "*px = %p\n", *px );
}
In this case the value stored in the original pointer will be changed within the function because the function using dereferencing access the same memory extent where the original pointer was defined.
Q: what is this (**)?
A: Yes, it's exactly that. A pointer to a
pointer.
Q: what use does it have?
A: It has a number of uses. Particularly in representing 2 dimensional data (images, etc). In the case of your example char** argv can be thought of as an array of an array of chars. In this case each char* points to the beginning of a string. You could actually declare this data yourself explicitly like so.
char* myStrings[] = {
"Hello",
"World"
};
char** argv = myStrings;
// argv[0] -> "Hello"
// argv[1] -> "World"
When you access a pointer like an array the number that you index it with and the size of the element itself are used to offset to the address of the next element in the array. You could also access all of your numbers like so, and in fact this is basically what C is doing. Keep in mind, the compiler knows how many bytes a type like int uses at compile time. So it knows how big each step should be to the next element.
*(numbers + 0) = 1, address 0x0061FF1C
*(numbers + 1) = 3, address 0x0061FF20
*(numbers + 2) = 4, address 0x0061FF24
*(numbers + 3) = 5, address 0x0061FF28
The * operator is called the dereference operator. It is used to retrieve the value from memory that is pointed to by a pointer. numbers is literally just a pointer to the first element in your array.
In the case of my example myStrings could look something like this assuming that a pointer/address is 4 bytes, meaning we are on a 32 bit machine.
myStrings = 0x0061FF14
// these are just 4 byte addresses
(myStrings + 0) -> 0x0061FF14 // 0 bytes from beginning of myStrings
(myStrings + 1) -> 0x0061FF18 // 4 bytes from beginning of myStrings
myStrings[0] -> 0x0061FF1C // de-references myStrings # 0 returning the address that points to the beginning of 'Hello'
myStrings[1] -> 0x0061FF21 // de-references myStrings # 1 returning the address that points to the beginning of 'World'
// The address of each letter is 1 char, or 1 byte apart
myStrings[0] + 0 -> 0x0061FF1C which means... *(myStrings[0] + 0) = 'H'
myStrings[0] + 1 -> 0x0061FF1D which means... *(myStrings[0] + 1) = 'e'
myStrings[0] + 2 -> 0x0061FF1E which means... *(myStrings[0] + 2) = 'l'
myStrings[0] + 3 -> 0x0061FF1F which means... *(myStrings[0] + 3) = 'l'
myStrings[0] + 4 -> 0x0061FF20 which means... *(myStrings[0] + 4) = 'o'
The traditional way to write the argv argument is char *argv[] which gives more information about what it is, an array of pointers to characters (i.e. an array of strings).
However, when passing an array to a function it decays to a pointer, leaving you with a pointer to pointer to char, or char **.
Of course, double asterisks can also be used when dereferencing a pointer to a pointer, so without the added context at the end of the question there are two answers to the question what ** means in C, depending on context.
To continue with the argv example, one way to get the first character of the first element in argv would be to do argv[0][0], or you could use the dereference operator twice, as in **argv.
Array indexing and dereferencing is interchangeable in most places, because for any pointer or array p and index i the expression p[i] is equivalent to *(p + i). And if i is 0 then we have *(p + 0) which can be shortened to *(p) which is the same as *p.
As a curiosity, because p[i] is equivalent to *(p + i) and the commutative property of addition, the expression *(p + i) is equal to *(i + p) which leads to p[i] being equal to i[p].
Finally a warning about excessive use of pointers, you might sometime hear the phrase three-star programmer, which is when one uses three asterisks like in *** (like in a pointer to a pointer to a pointer). But to quote from the link
Just to be clear: Being called a ThreeStarProgrammer is usually not a compliment
And another warning: An array of arrays is not the same as a pointer to a pointer (Link to an old answer of mine, which also shows the memory layout of a pointer to a pointer as a substitute of an array of arrays.)
** in declaration represents pointer to pointer. Pointer is itself a data type and like other data types it can have a pointer.
int i = 5, j = 6; k = 7;
int *ip1 = &i, *ip2 = &j;
int **ipp = &ip1;
Pointer to pointer are useful in case of allocating dynamic 2D array. To allocate a 10x10 2D array (may not be contiguous)
int **m = malloc(sizeof(int *)*10;
for(int i = 0; i < 10; i++)
m[i] = malloc(sizeof(int)*10
It is also used when you want to change the value of a pointer through a function.
void func (int **p, int n)
{
*p = malloc(sizeof(int)*n); // Allocate an array of 10 elements
}
int main(void)
{
int *ptr = NULL;
int n = 10;
func(&ptr, n);
if(ptr)
{
for(int i = 0; i < n; i++)
{
ptr[i] = ++i;
}
}
free(ptr);
}
Further reading: Pointer to Pointer.
** represents a pointer to a pointer. If you want to pass a parameter by reference, you would use *, but if you want to pass the pointer itself by reference, then you need a pointer to the pointer, hence **.
** stands for pointer to pointer as you know the name. I will explain each of your question:
what is this (**)?
Pointer to Pointer. Sometime people call double pointer. For example:
int a = 3;
int* b = &a; // b is pointer. stored address of a
int**b = &b; // c is pointer to pointer. stored address of b
int***d = &c; // d is pointer to pointer to pointer. stored address of d. You get it.
how is it represented in memory?
c in above example is just a normal variable and has same representation as other variables (pointer, int ...). Memory size of variable c same as b and it depends on platform. For example, 32-bit computer, each variable address includes 32bit so size will be 4 bytes (8x4=32 bit) On 64-bit computer, each variable address will be 64bit so size will be 8 bytes (8x8=64 bit).
what use does it have?
There are many usages for pointer to pointer, depends on your situation. For example, here is one example I learned in my algorithm class. You have a linked list. Now, you want to write a method to change that linked list, and your method may changed head of linked list. (Example: remove one element with value equals to 5, remove head element, swap, ...). So you have two cases:
1. If you just pass a pointer of head element. Maybe that head element will be removed, and this pointer doesn't valid anymore.
2. If you pass pointer of pointer of head element. In case your head element is removed, you meet no problem because the pointer of pointer still there. It just change values of another head node.
You can reference here for above example: pointer to pointer in linked list
Another usage is using in two-dimensional array. C is different from Java. Two dimensional array in C, in fact just a continuous memory block. Two dimensional array in Java is multi memory block (depend on your row of matrix)
Hope this help :)
Consider if you have a table of pointers - such as a table of strings (since strings in "C" are handled simply as pointers to the first character of the string).
Then you need a pointer to the first pointer in the table. Hence the "char **".
If you have an inline table with all the values, like a two-dimensional table of integers, then it's entirely possible to get away with only one level of indirection (i.e. just a simple pointer, like "int *"). But when there is a pointer in the middle that needs to be dereferenced to get to the end result, that creates a second level of indirection, and then the pointer-to-pointer is essential.
Another clarification here. In "C", dereferencing via pointer notation (e.g. "*ptr") vs array index notation (e.g. ptr[0]) has little difference, other than the obvious index value in array notation. The only time asterisk vs brackets really matters is when allocating a variable (e.g. int *x; is very different than int x[1]).
Of your int * example you say
And I'm guessing it would be of size 4 bytes?
Unlike Java, C does not specify the exact sizes of its data types. Different implementations can and do use different sizes (but each implementation must be consistent). 4-byte ints are common these days, but ints can be as small two bytes, and nothing inherently limits them to four. The size of pointers is even less specified, but it usually depends on the hardware architecture at which the C implementation is targeted. The most common pointer sizes are four bytes (typical for 32-bit architectures) and eight bytes (common for 64-bit architectures).
what is this (**)?
In the context you present, it is part of the type designator char **, which describes a pointer to a pointer to char, just as you thought.
what use does it have?
More or less the same uses as a pointer to any other data type. Sometimes you want or need to access a pointer value indirectly, just like you may want or need to access a value of any other type indirectly. Also, it's useful for pointing to (the first element of) an array of pointers, which is how it is used in the second parameter to a C main() function.
In this particular case, each char * in the pointed-to array itself points to one of the program's command-line arguments.
how is it represented in memory?
C does not specify, but typically pointers to pointers have the same representation as pointers to any other type of value. The value it points to is simply a pointer value.
First of all, remember that C treats arrays very differently from Java. A declaration like
char foo[10];
allocates enough storage for 10 char values and nothing else (modulo any additional space to satisfy alignment requirements); no additional storage is set aside for a pointer to the first element or any other kind of metadata such as array size or element class type. There's no object foo apart from the array elements themselves1. Instead, there's a rule in the language that anytime the compiler sees an array expression that isn't the operand of the sizeof or unary & operator (or a string literal used to initialize another array in a declaration), it implicitly converts that expression from type "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element of the array.
This has several implications. First is that when you pass an array expression as an argument to a function, what the function actually receives is a pointer value:
char foo[10];
do_something_with( foo );
...
void do_something_with( char *p )
{
...
}
The formal parameter p corresponding to the actual parameter foo is a pointer to char, not an array of char. To make things confusing, C allows do_something_with to be declared as
void do_something_with( char p[] )
or even
void do_something_with( char p[10] )
but in the case of function parameter declarations, T p[] and T p[N] are identical to T *p, and all three declare p as a pointer, not an array2. Note that this is only true for function parameter declarations.
The second implication is that the subscript operator [] can be used on pointer operands as well as array operands, such as
char foo[10];
char *p = foo;
...
p[i] = 'A'; // equivalent to foo[i] = 'A';
The final implication leads to one case of dealing with pointers to pointers - suppose you have an array of pointers like
const char *strs[] = { "foo", "bar", "bletch", "blurga", NULL };
strs is a 5-element array of const char *3; however, if you pass it to a function like
do_something_with( strs );
then what the function receives is actually a pointer to a pointer, not an array of pointers:
void do_something_with( const char **strs ) { ... }
Pointers to pointers (and higher levels of indirection) also show up in the following situations:
Writing to a parameter of pointer type: Remember that C passes all parameters by value; the formal parameter in the function definition is a different object in memory than the actual parameter in the function call, so if you want the function to update the value of the actual parameter, you must pass a pointer to that parameter:
void foo( T *param ) // for any type T
{
*param = new_value(); // update the object param *points to*
}
void bar( void )
{
T x;
foo( &x ); // update the value in x
}
Now suppose we replace the type T with the pointer type R *, then our code snippet looks like this:
void foo( R **param ) // for any type R *
{
...
*param = new_value(); // update the object param *points to*
...
}
void bar( void )
{
R *x;
foo( &x ); // update the value in x
}
Same semantics - we're updating the value contained in x. It's just that in this case, x already has a pointer type, so we must pass a pointer to the pointer. This can be extended to higher levels of direction:
void foo( Q ****param ) // for any type Q ***
{
...
*param = new_value(); // update the object param *points to*
...
}
void bar( void )
{
Q ***x;
foo( &x ); // update the value in x
}
Dynamically-allocated multi-dimensional arrays: One common technique for allocating multi-dimensional arrays in C is to allocate an array of pointers, and for each element of that array allocate a buffer that the pointer points to:
T **arr;
arr = malloc( rows * sizeof *arr ); // arr has type T **, *arr has type T *
if ( arr )
{
for ( size_t i = 0; i < rows; i++ )
{
arr[i] = malloc( cols * sizeof *arr[i] ); // arr[i] has type T *
if ( arr[i] )
{
for ( size_t j = 0; j < cols; j++ )
{
arr[i][j] = some_initial_value();
}
}
}
}
This can be extended to higher levels of indirection, so you have have types like T *** and T ****, etc.
1. This is part of why array expressions may not be the target of an assignment; there's nothing to assign anything to.
This is a holdover from the B programming language from which C was derived; in B, a pointer is declared as auto p[].
Each string literal is an array of char, but because we are not using them to initialize individual arrays of char, the expressions are converted to pointer values.
I think I'm going to add my own answer in here as well as everyone has done an amazing job but I was really confused at what the point of a pointer to a pointer was. The reason why I came up with this is because I was under the impression that all the values except pointers, were passed by value, and pointers were passed by reference. See the following:
void f(int *x){
printf("x: %d\n", *x);
(*x)++;
}
void main(){
int x = 5;
int *px = &x;
f(px);
printf("x: %d",x);
}
would produce:
x: 5
x: 6
This made my think (for some reason) that pointers were passed by reference as we are passing in the pointer, manipulating it and then breaking out and printing the new value. If you can manipulate a pointer in a function... why have a pointer to a pointer in order to manipulate the pointer to begin with!
This seemed wrong to me, and rightly so because it would be silly to have a pointer to manipulate a pointer when you can already manipulate a pointer in a function. The thing with C though; is everything is passed by value, even pointers. Let me explain further using some pseudo values instead of the addresses.
//this generates a new pointer to point to the address so lets give the
//new pointer the address 0061FF28, which has the value 0061FF1C.
void f(int 0061FF1C){
// this prints out the value stored at 0061FF1C which is 5
printf("x: %d\n", 5);
// this FIRST gets the value stored at 0061FF1C which is 5
// then increments it so thus 6 is now stored at 0061FF1C
(5)++;
}
void main(){
int x = 5;
// this is an assumed address for x
int *px = 0061FF1C;
/*so far px is a pointer with the address lets say 0061FF24 which holds
*the value 0061FF1C, when passing px to f we are passing by value...
*thus 0061FF1C is passed in (NOT THE POINTER BUT THE VALUE IT HOLDS!)
*/
f(px);
/*this prints out the value stored at the address of x (0061FF1C)
*which is now 6
*/
printf("x: %d",6);
}
My main misunderstanding of pointers to pointers is the pass by value vs pass by reference. The original pointer was not passed into the function at all, so we cannot change what address it is pointing at, only the address of the new pointer (which has the illusion of being the old pointer as its pointing to the address the old pointer was pointing to!).
It is a pointer to a pointer. If you are asking why you would want to use a pointer to a pointer, here is a similar thread that answers that in a variety of good ways.
Why use double pointer? or Why use pointers to pointers?
For example, ** is a pointer to a pointer. char **argv is the same as char *argv[] and this is the same with char argv[][]. It's a matrix.
You can declare a matrix with 4 lines, for example, but different number of columns, like JaggedArrays.
It is represented as a matrix.
Here you have a representation in memory.
I would understand char **argv as char** argv. Now, char* is basically an array of char, so (char*)* is an array of arrays of char.
In other (loose) words, argv is an array of strings. In this particular example: the call
myExe dummyArg1 dummyArg2
in console would make argv as
argv[0] = "myExe"
argv[1] = "dummyArg1"
argv[2] = "dummyArg2"
In fact, in C arrays are pointers :
char* string = "HelloWorld!";
is equivalent to this : char string[] = "HelloWorld";
And this : char** argv is as you said a "pointer to a pointer".
It can be seen as an array of strings, i.e multiple strings. But remember that strings are char pointers!
See : in Java the main method is similar to the C main function. It's something like this :
public static void main(String[] args){}
I.e an array of strings. It works the same way in C, String[] args becomes char** args or char* args[].
To sum up : type* name = blablabla;
is potentially an array of "type".
And type** name = blabla; is potentially an array of arrays.

Strange (for me) behavior of pointers

I'm reading about pointers, but i'm confused about their nature. Here is what I mean.
int x = 4;
//Here I declare p as integer pointer
int *p;
// Here I assign memory address of x to pointer p
p = &x;
// The line below prints result 4 which is expected. If I miss asterisk before p I'll get memory address instead of data which that memory address holds.
printf("%d", *p)
Summarizing when asterisk is mising before pointer it "points" to memory address. If asterisk preceded pointer it "points" to actual data.
So far so good.
But why that segment of code works correctly ?
int someIntVariable = 10;
const int *p = &someIntVariable;
printf("%d", *p);
If I miss asterisk the compiler gives me an warning " warning: initialization makes integer from pointer without a cast"
I expected p (if the compiler allows me to use p without asterisk) to hold memory address of someIntVariable instead of it's "value";
What is happening here ?
In the declaration:
const int *p = &someIntVariable;
The asterisk is not the dereference operator. It simply states p is a pointer. That line has the same effect as
const int *p;
p = &someIntVariable;
Here you are declaring a pointer and assigning a value to the pointer in one step.
It is equivalent to the following code:
const int *p;
p = &someIntVariable;
Here the * is not used as a de-referencing operator. It is used in the context of pointer declaration.
The const int * is a datatype - i.e. pointer to a const int. p is the name of the variable. It is on the LHS.
When asterik is on the RHS it has a different meaning. It means dereference.
I belive you got the warning:initialization makes integer from pointer without a cast,
when you tried these way
int someIntVariable = 10;
const int p = &someIntVariable;
printf("%d", p);
What your trying to do is , Your assigning a address to a normal variable and your expecting it to work but that is not how the normal variables used thats why pointers came into act to do that job and your trying to replace a pointer with normal variable
I still did not find the real answer to it but Just check out these question that I asked I wonder what really the &a returns?

Is an array name a pointer?

Is an array's name a pointer in C?
If not, what is the difference between an array's name and a pointer variable?
An array is an array and a pointer is a pointer, but in most cases array names are converted to pointers. A term often used is that they decay to pointers.
Here is an array:
int a[7];
a contains space for seven integers, and you can put a value in one of them with an assignment, like this:
a[3] = 9;
Here is a pointer:
int *p;
p doesn't contain any spaces for integers, but it can point to a space for an integer. We can, for example, set it to point to one of the places in the array a, such as the first one:
p = &a[0];
What can be confusing is that you can also write this:
p = a;
This does not copy the contents of the array a into the pointer p (whatever that would mean). Instead, the array name a is converted to a pointer to its first element. So that assignment does the same as the previous one.
Now you can use p in a similar way to an array:
p[3] = 17;
The reason that this works is that the array dereferencing operator in C, [ ], is defined in terms of pointers. x[y] means: start with the pointer x, step y elements forward after what the pointer points to, and then take whatever is there. Using pointer arithmetic syntax, x[y] can also be written as *(x+y).
For this to work with a normal array, such as our a, the name a in a[3] must first be converted to a pointer (to the first element in a). Then we step 3 elements forward, and take whatever is there. In other words: take the element at position 3 in the array. (Which is the fourth element in the array, since the first one is numbered 0.)
So, in summary, array names in a C program are (in most cases) converted to pointers. One exception is when we use the sizeof operator on an array. If a was converted to a pointer in this context, sizeof a would give the size of a pointer and not of the actual array, which would be rather useless, so in that case a means the array itself.
When an array is used as a value, its name represents the address of the first element.
When an array is not used as a value its name represents the whole array.
int arr[7];
/* arr used as value */
foo(arr);
int x = *(arr + 1); /* same as arr[1] */
/* arr not used as value */
size_t bytes = sizeof arr;
void *q = &arr; /* void pointers are compatible with pointers to any object */
If an expression of array type (such as the array name) appears in a larger expression and it isn't the operand of either the & or sizeof operators, then the type of the array expression is converted from "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element in the array.
In short, the array name is not a pointer, but in most contexts it is treated as though it were a pointer.
Edit
Answering the question in the comment:
If I use sizeof, do i count the size of only the elements of the array? Then the array “head” also takes up space with the information about length and a pointer (and this means that it takes more space, than a normal pointer would)?
When you create an array, the only space that's allocated is the space for the elements themselves; no storage is materialized for a separate pointer or any metadata. Given
char a[10];
what you get in memory is
+---+
a: | | a[0]
+---+
| | a[1]
+---+
| | a[2]
+---+
...
+---+
| | a[9]
+---+
The expression a refers to the entire array, but there's no object a separate from the array elements themselves. Thus, sizeof a gives you the size (in bytes) of the entire array. The expression &a gives you the address of the array, which is the same as the address of the first element. The difference between &a and &a[0] is the type of the result1 - char (*)[10] in the first case and char * in the second.
Where things get weird is when you want to access individual elements - the expression a[i] is defined as the result of *(a + i) - given an address value a, offset i elements (not bytes) from that address and dereference the result.
The problem is that a isn't a pointer or an address - it's the entire array object. Thus, the rule in C that whenever the compiler sees an expression of array type (such as a, which has type char [10]) and that expression isn't the operand of the sizeof or unary & operators, the type of that expression is converted ("decays") to a pointer type (char *), and the value of the expression is the address of the first element of the array. Therefore, the expression a has the same type and value as the expression &a[0] (and by extension, the expression *a has the same type and value as the expression a[0]).
C was derived from an earlier language called B, and in B a was a separate pointer object from the array elements a[0], a[1], etc. Ritchie wanted to keep B's array semantics, but he didn't want to mess with storing the separate pointer object. So he got rid of it. Instead, the compiler will convert array expressions to pointer expressions during translation as necessary.
Remember that I said arrays don't store any metadata about their size. As soon as that array expression "decays" to a pointer, all you have is a pointer to a single element. That element may be the first of a sequence of elements, or it may be a single object. There's no way to know based on the pointer itself.
When you pass an array expression to a function, all the function receives is a pointer to the first element - it has no idea how big the array is (this is why the gets function was such a menace and was eventually removed from the library). For the function to know how many elements the array has, you must either use a sentinel value (such as the 0 terminator in C strings) or you must pass the number of elements as a separate parameter.
Which *may* affect how the address value is interpreted - depends on the machine.
An array declared like this
int a[10];
allocates memory for 10 ints. You can't modify a but you can do pointer arithmetic with a.
A pointer like this allocates memory for just the pointer p:
int *p;
It doesn't allocate any ints. You can modify it:
p = a;
and use array subscripts as you can with a:
p[2] = 5;
a[2] = 5; // same
*(p+2) = 5; // same effect
*(a+2) = 5; // same effect
The array name by itself yields a memory location, so you can treat the array name like a pointer:
int a[7];
a[0] = 1976;
a[1] = 1984;
printf("memory location of a: %p", a);
printf("value at memory location %p is %d", a, *a);
And other nifty stuff you can do to pointer (e.g. adding/substracting an offset), you can also do to an array:
printf("value at memory location %p is %d", a + 1, *(a + 1));
Language-wise, if C didn't expose the array as just some sort of "pointer"(pedantically it's just a memory location. It cannot point to arbitrary location in memory, nor can be controlled by the programmer). We always need to code this:
printf("value at memory location %p is %d", &a[1], a[1]);
I think this example sheds some light on the issue:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
int **b = &a;
printf("a == &a: %d\n", a == b);
return 0;
}
It compiles fine (with 2 warnings) in gcc 4.9.2, and prints the following:
a == &a: 1
oops :-)
So, the conclusion is no, the array is not a pointer, it is not stored in memory (not even read-only one) as a pointer, even though it looks like it is, since you can obtain its address with the & operator. But - oops - that operator does not work :-)), either way, you've been warned:
p.c: In function ‘main’:
pp.c:6:12: warning: initialization from incompatible pointer type
int **b = &a;
^
p.c:8:28: warning: comparison of distinct pointer types lacks a cast
printf("a == &a: %d\n", a == b);
C++ refuses any such attempts with errors in compile-time.
Edit:
This is what I meant to demonstrate:
#include <stdio.h>
int main()
{
int a[3] = {9, 10, 11};
void *c = a;
void *b = &a;
void *d = &c;
printf("a == &a: %d\n", a == b);
printf("c == &c: %d\n", c == d);
return 0;
}
Even though c and a "point" to the same memory, you can obtain address of the c pointer, but you cannot obtain the address of the a pointer.
The following example provides a concrete difference between an array name and a pointer. Let say that you want to represent a 1D line with some given maximum dimension, you could do it either with an array or a pointer:
typedef struct {
int length;
int line_as_array[1000];
int* line_as_pointer;
} Line;
Now let's look at the behavior of the following code:
void do_something_with_line(Line line) {
line.line_as_pointer[0] = 0;
line.line_as_array[0] = 0;
}
void main() {
Line my_line;
my_line.length = 20;
my_line.line_as_pointer = (int*) calloc(my_line.length, sizeof(int));
my_line.line_as_pointer[0] = 10;
my_line.line_as_array[0] = 10;
do_something_with_line(my_line);
printf("%d %d\n", my_line.line_as_pointer[0], my_line.line_as_array[0]);
};
This code will output:
0 10
That is because in the function call to do_something_with_line the object was copied so:
The pointer line_as_pointer still contains the same address it was pointing to
The array line_as_array was copied to a new address which does not outlive the scope of the function
So while arrays are not given by values when you directly input them to functions, when you encapsulate them in structs they are given by value (i.e. copied) which outlines here a major difference in behavior compared to the implementation using pointers.
NO. An array name is NOT a pointer. You cannot assign to or modify an array name, but you can for a pointer.
int arr[5];
int *ptr;
/* CAN assign or increment ptr */
ptr = arr;
ptr++;
/* CANNOT assign or increment arr */
arr = ptr;
arr++;
/* These assignments are also illegal */
arr = anotherarray;
arr = 0;
From K&R Book:
There is one difference between an array name and a pointer that must
be kept in mind. A pointer is a variable, but an array name is not a
variable.
sizeof is the other big difference.
sizeof(arr); /* size of the entire array */
sizeof(ptr); /* size of the memory address */
Arrays do behave like or decay into a pointer in some situations (&arr[0]). You can see other answers for more examples of this. To reiterate a few of these cases:
void func(int *arr) { }
void func2(int arr[]) { } /* same as func */
ptr = arr + 1; /* pointer arithmetic */
func(arr); /* passing to function */
Even though you cannot assign or modify the array name, of course can modify the contents of the array
arr[0] = 1;
The array name behaves like a pointer and points to the first element of the array. Example:
int a[]={1,2,3};
printf("%p\n",a); //result is similar to 0x7fff6fe40bc0
printf("%p\n",&a[0]); //result is similar to 0x7fff6fe40bc0
Both the print statements will give exactly same output for a machine. In my system it gave:
0x7fff6fe40bc0

Resources