This question already has answers here:
How do pointer-to-pointers work in C? (and when might you use them?)
(14 answers)
Closed 6 years ago.
I am beginner of C Programming language. I saw a code on the book:
#include<stdio.h>
int main(){
int * * k, *a, b=100;
a = &b;
k = &a;
printf("%d\n",* * k);
}
I don't know the meaning of int * *k. Is that a integer pointer or value? what will it point to? what will it contains/store? what's the use of this variable? How can I understand this expression?
int **k
k is a pointer to pointer to int(double pointer) and holds an address of some other pointer variable.
In your example:
int b = 100; /* 'b' is an int, initialized to value 100 */
int *a = &b; /* a is a pointer-to-int*/
int **k = &a; /* k is a pointer-to-pointer-to-int */
See below picture for better understanding:
int** k is a pointer to an int pointer.
It stores a memory address, in that memory address there another memory address in which some integer value is stored.
It's called double pointer. It can be used to store address from single pointer.
You can also create triple pointer to store address from double pointer.
Example: int ***k;
This is called pointer to a pointer.
Here, the output for **k is 100, the value of b.
*(*k) = *(a) = *(address of b) = value of b
*k
means some code will get a value from address k later.
*(*k)
means some code will get a value from address (*k) later.
int **k
means k is intended to be used for address dereferencing for integer use but with a second level. Having this * character just behind a variable name at its definition, makes it a pointer. So k is a pointer to a pointer to an integer.
To get the value of cell that a pointer points to,
*k
is used just like in the definition. Then when it is a second-order pointer then
**k
is used to get its pointed value.
Related
This question already has answers here:
Difference between different ways of initializing pointers in c
(7 answers)
why is assigning values to int pointers different to that from char pointers?
(4 answers)
Closed 8 months ago.
What's the difference between 1 and 2?
int *p;
p = malloc(2 * sizeof(int));
int *p = malloc(2 * sizeof(int));
The way I first learned it is number 1, but I've seen someone do it number 2.
Is number 1 and 2 the same thing? I'm assuming it is, but
I'm confused because I don't understand why number 2 is
int *p = malloc(2 * sizeof(int));
not
int p = malloc(2 * sizeof(int));
The way he used it was for array. Later in the code, he used p to save some desired values.
Like this.
p[0] = i;
p[1] = j;
(1) and (2) are the same which are used to initialize pointer with memory allocation.
I think you're confused with the way to initialize pointer, not how to use malloc(). Take a look on some articles about "Initialize pointer" like this one.
int number = 88; // An int variable with a value
int * pNumber; // Declare a pointer variable called pNumber pointing to an int (or int pointer)
pNumber = &number; // Assign the address of the variable number to pointer pNumber
int * pAnother = &number; // Declare another int pointer and init to address of the variable number
int p = malloc(2 * sizeof(int));
This way is not correct to declare a pointer, in this case, p is just an integer variable, not a pointer that points to an integer variable.
What's the difference between 1 and 2?
1 and 2 do the same thing. The compiler should produce exactly the same code. They both declare a variable p of type int * and then initialize p with the pointer returned from malloc.
It's int *p = ... because int * is the type. The variable is p. It is declaring the variable p as the type int * and then assigning to p.
The difference is that 2 does it in a single statement. This is preferable because it ensures the variable is initialized, and it makes it easier to see that the variable is initialized. Uninitialized variables contain garbage and are a common source of errors. It's usually a good idea to initialize every variable immediately, even if it's to 0 or NULL.
You will often see code which declares and initializes variables separately; sometimes all the variables are declared at the top of each function. This is an old style from way back when C required you to declare all your variables at the start of a function. This is no longer an issue. You can declare variables as needed now.
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").
I have to questions about pointers; one theoretical and one practical.
Why, when declaring a pointer in C, must I preface the *var with a type. If a pointer is simply a variable that contains a memory address why does the compiler/language need any more information than that it is a pointer. What is the difference between an int * and a char *. Does this imply that an int * is pointing a some location that contains 2-4 bytes of memory and a char * contains only 1? I have never read anything about the underlying reasoning for why the type matters if ultimately it is a variable pointing to some hexadecimal number as evidence by %p printing them.
Secondly, given this code
int t = 10;
int *i = &t;
int *j = i;
--
*i == 10;
*j == 10;
Why is it that *j is equal to 10 instead of **j being 10? If j is a pointer to i which is a pointer to t which is 10 don't i need to double dereference the variable j? When writing this code in xcode it forces me to use *j.
So these are a few examples of confusion I have had with pointers.
The datatype is required in order to know how many bytes to read when the pointer is dereferenced.
int *i = &t;
Here, the value stored in i is the address of t.
int *j = i;
So now, the value stored in j is the value stored in i which is the address of t. If you wanted to do a double dereference, you'd need to store the address of i.
int **j = &i
why does the compiler/language need any more information than that it is a pointer
To use the pointer only, the compiler doesn't. The type void* means "a pointer to anything".
However, to use the value that is being pointed to, the compiler needs to know the type of what is being pointed to, so that it knows what can be done with it. Dereferencing a void* will cause a compiler error, unless you first cast it to a typed pointer.
Secondly, given this code
j is not a pointer to i. The assignment int *j = i; sets j to the same value as i, which is the address to t (so j would now point to t).
To make j a pointer to i, you would need to declare it as int **j = &i;
why does the compiler/language need any more information than that it is a pointer.
That's because different data types are of different size and size of data types are needed to allocate memory.
What is the difference between an int * and a char *.
int * is a pointer to int and char * is a pointer to a char.
Why is it that *j is equal to 10 instead of **j being 10? If j is a pointer to i which is a pointer to t which is 10 don't i need to double dereference the variable j?
int *j = i; tells the compiler that declare j as pointer to int and point this pointer to the memory location where pointer i points to. Therefore j is a pointer to variable t.
C is a statically typed language. There are other languages, like JavaScript for example, which are dynamically typed, where you can assign objects of different types to the same variable.
Both approaches have their advantages and disadvantages, the most important advantage of statically typed languages is that many errors can be caught at compilation.
It's a design decision.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is array name a pointer in C?
I was running the following code
#include <stdio.h>
int main()
{
int a[4] = {1,2,3,4};
int (*b)[4] = &a;
int k = sizeof(a);
printf("\n\n%d\n\n", k);
printf("a = %u, b = %u, *b = %u, data = %d", a, b, *b, **b);
return 0;
}
I got the following output
a = 3485401628, b = 3485401628, *b = 3485401628, data = 1
Here I am assigning the address of a to b, as the type of b is int**, but in the output I am getting that the address pointed by the a is the same as the address pointed by b.
It seems little confusing to me. What is the explanation?
The value of array a is the pointer to the first element of the array a.
The value of pointer &a (which is the same value and type as pointer b) is the pointer to the array a.
They have the same value (but different types) as they both start at the same memory address. There is no padding possible at the beginning of an array.
When evaluated a is of type int * and &a is of type int (*)[4].
Note that the correct way to print the address of a pointer is to use conversion specifier p. E.g.,
/* And p requires the argument to be a void *, so use a cast if
* it is not the case
*/
printf("%p %p\n", (void *) a, (void *) &a);
On expressions (such as an argument for printf) arrays are decayed to pointers (to their respective arrays), meaning that if "b" points to "a", on an expression, "a" will also be a pointer to "a" (the block of memory allocated for "a").
The way of accessing elements at runtime however (internally), is different. In this case, "b" would require an additional indirection.
I know that pointers contain the addresses of variables, for example:
int c = 5;
int *p;
p = &c;
printf("%d",*p); // Outputs 5.
But what if I want to send an address to a function:
void function (int *p)
{
p++;
}
int c;
function (&c);
When function is called, the value of &c is assigned to int *p. I guess that the exact instruction is: *p = &c;, but I don't understand what this means.
I prefer to write int* p = &c;, that is, a pointer to type int is being assigned the address of c.
Pointer notation can be confusing, as you've noticed, because these two are equivalent:
int *p = &c;
and
int *p;
p = &c;
Hope this helps!
EDIT: The confusion comes because * is used both as the dereference operator, and for declaring a pointer. So when p contains the address of c, *p dereferences the pointer and returns the value of c. But when you say int *p = &c;, the * is saying "p is a pointer to an int", but is not doing any dereferencing.
*p = &c; means:
Get the address of c in memory which is determined at compile-time link-time (Thanks Mikeage) e.g, 0x1234 as an example. The pointer to type int, i.e. *p is assigned to 0x1234, which does not sound right to me, I think you should be doing it this way, p = &c then *p would have the value pointed to by the address of c. And therefore *p would have the value of what c was assigned to (that is called dereferencing - by putting a * before the pointer variable then you can obtain the value).
In your function you are trying to increment the value pointed to by p.
void function (int *p)
{
*p++;
}
// It would be called like this
int c = 5;
function(&c); // Now c would have 6!
The key point is you want to pass by reference which is what the parameter &c does.
If you omit the passing by reference like this:
void function (int p)
{
p++;
}
// And call it like this
int c = 5;
function(c); // c is still 5
Now c would still be 5, but within the function itself c is 6, but no copy is passed back out as it is incremented within the local stack for the function itself.
I can't really make out your question, but the function looks like bug to me and what you meant is, perhaps,
++(*p)
Otherwise it's a no-op.
If you want the function to increment c when called with &c, then write this:
void function(int *p) { ++(*p); }
function(int *p) means that p is the function parameter. So whatever value the caller gives, that will be assigned to p (not to *p).
The type of p is int *. That is, p is a pointer-to-int.
If p is a pointer-to-int, then *p is the int it points to.
c is an int. Therefore &c is a pointer-to-int, and the int it points to is c. Therefore, if p is &c, then *p is c.
With my version of the function, this code:
int c = 5;
function(&c);
Does the same as this code:
int c = 5; // same as before
int *p; // parameter of the function
p = &c; // assign the caller's value to the parameter
++(*p); // body of the function, increments *p, which is the same as c.
Which does the same as this code:
int c = 5;
++c;
Are you sure p++; is what you mean to do in your function? That's incrementing the location pointed to by p, it's not incrementing the value at the current location. If you're wanting to increment the value (i.e. make c become 6), then what you want is (*p)++;.
Others have answered your question. I will just add that a helpful way of reading pointer declarations is this. Let's say I have the following declaration:
int i;
This is really easy. Here, i is an int. Now, let's say I have this:
int *pi;
Here, you can either say that pi is a pointer to an int (which is correct). Another way to look at it would be that *pi is an int, i.e., when you have *pi in your code, that *pi will be of type int. Having understood that, I think it's easy to see that ++pi or pi++ doesn't increment the int, because pi is the wrong type. You want (*pi)++. The parentheses are needed because in C, the operator ++ has higher precedence than the unary operator *. Since you don't use any of the side effects of the increment, you can as well do: ++*p.
Of course, as with all the pointers, pi has to point to something useful for the above to make sense.