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 3 years ago.
Improve this question
I was expecting a garbage value from the first printf() statement but I got the address instead. Why?
#include<stdio.h>
int main()
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p=a+10;
printf("%d\n",*(p));
printf("%u",(p));
}
For starters this statement
p=a+10;
is invalid.
The left side of the assignment has the type int( * )[10] while the right side of the assignment has the type int * and there is no implicit conversion from one type to another.
You have to write
p = ( int( * )[10] )( a + 10 );
Secondly these calls of printf
printf("%d\n",*(p));
printf("%u",(p));
have undefined behavior because there are used invalid conversion specifier d and u with arguments of pointer types because *p and p are both pointers.
So a valid program can look the following way
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a + 10 );
printf("%p\n",( void * )*p );
printf("%p\n", (void *)p );
return 0;
}
A pointer may point to the memory that follows the last element of an object (or an array).
So after this statement
p = ( int( * )[10] )( a+10 );
the pointer p points after the first element of an imagined two-dimensional array elements of which in turn one-dimensional arrays of the type int[10] and the first element of the imagined two-dimensional array corresponds to the array a.
The expression *p is also a pointer. Its type is int * because the expression *p gives an lvalue of the type int[10] and in expressions this lvalue is implicitly converted to pointer to its first element (in this case of the type int).
So the both expressions p and *p points to the same memory and have the same value.
This is demonstrated by the program output
0x7ffcfd46ea48
0x7ffcfd46ea48
The difference between these two pointers, p and *p, is the type of an object they potentially point to.
Consider the following demonstrative program
#include <stdio.h>
int main(void)
{
int (*p)[10];
int a[10]={1,2,3,4,5,6,7,8,9,0};
p = ( int( * )[10] )( a+10 );
printf("%zu\n",sizeof( *p ) );
printf("%zu\n",sizeof( **p ) );
return 0;
}
Its output is
40
4
You could get undefined behavior if you wrote
printf( "%d\n", **p );
In this case the expression **p has the type int and there is an access to the memory beyond the array a.
Given this declaration:
int (*p)[10];
p is a pointer to an array. The expression *p therefore designates the pointed-to array itself. But in almost all C contexts, including in particular when it is an argument in a function call expression, the value of an expression of array type is automatically converted to a pointer to the first element of the array. The address of that element is the same as the address of the array itself, so if p is in fact a valid pointer then it is entirely reasonable for
printf("%p\n", (void *) (*p));
printf("%p\n", (void *) (p));
to print two identical lines.
Do note, however, the use of the %p format directive instead of %u or %d for printing a (void) pointer value, and the casts to void *. These changes to your original code are necessary for the behavior of the printf calls to be well defined.
It is true that as far as the C language is concerned, *p does not designate an object in your case, so in that sense, evaluating the expression *p produces undefined behavior. This is one of the reasons why I say only that it is "reasonable" for the code to emit two identical lines. In practice, however, implementations are likely to treat the expression *p identically to (int *) p, whose behavior is well-defined in this case.
You should also be aware -- and your compiler should be warning you -- that the expression a + 10 has the wrong type (int *) to be assigned directly to your p (an int (*)[10]). It is allowed to convert between those two types, but a cast is required:
p = (int (*)[10])(a + 10);
or
p = (void *)(a + 10);
There is good reason to expect that your compiler is compiling the original assignment expression as if the required cast were present, especially inasmuch as it is a no-op in many implementations, probably including yours, but you should not rely on that.
The array can be treated as (decays to) a pointer to the first element.
When you take the address of an array, you generate a pointer to the array, generally to the same address as first element
When you dereference the pointer to array, you get pointer to element, which generally has the same actual numeric value.
I say generally, because some strange C emulator, or some system that puts an extra indirection in all pointer objects, might decide that the array and the content of the array are 2 different objects.
Related
I am trying to understand the significance of these two operators, so I wrote this code just for that purpose.
#include <stdio.h>
#include <string.h>
int main()
{
char *mnemonic, *operands;
mnemonic = "add";
operands = "five to two";
analyse_inst(mnemonic, operands);
}
void analyse_inst(char mnemonic, char operands)
{
printf("%s", mnemonic);
printf("%s", operands);
}
However, I noticed that it wouldn't work unless I change the arguments of analyse_inst() function to analyse_inst(char * mnemonic, char * operands), which means that I will be passing pointers to the function. But why is that required?
Also, I looked up about "passing by reference." And according to tutorialspoint.com, its definition:
The call by reference method of passing arguments to a function copies
the address of an argument into the formal parameter. Inside the
function, the address is used to access the actual argument used in
the call. It means the changes made to the parameter affect the passed
argument.
From that, I got that passing a variable by reference and then modifying that value would mean that the same variable outside the function would be changed as well; whereas for passing a variable by value would not change the same variable located outside the function.
Am I going wrong anywhere?
How can I can modify my code such that I am passing the two variables by reference?
(P.S. I have read other Stack Overflow threads on the same topic, but I would appreciate it if anyone could explain it in the context of the code I wrote)
which means that I will be passing pointers to the function. But why is that required?
Because what you have in main are pointers, and what printf("%s" expects is a char*.
"Pass by reference" is a broad term in programming, meaning passing along an address rather than a copy of the object. In your case, you pass a pointer to the first element of each string, rather than making a copy of the whole string, since that would waste execution time and memory.
So while the strings themselves could be said to be "passed by reference", strictly speaking C actually only allows parameters to be passed by value. The pointers themselves are passed by value. Your function parameters will be copies of the pointers you have allocated in main(). But they point at the same strings as the pointers in main() do.
From that, I got that passing a variable by reference and then modifying that value would mean that the same variable outside the function would be changed as well;
Indeed, you could change the string from inside the function through the pointer and then it would affect the string in main(). But in this case, you haven't allocated any memory to modify - you would attempt to modify a string literal "...", which would have been a bug. If you were to modify the strings, you should have declared them as arrays in main(): char mnemonic[] = "add";
Now as it turns out, whenever you use an array like the one in my example inside an expression, it "decays" into a pointer to the first element. So we wouldn't actually be able to pass the array by value to the function, as the C language would have changed it between the lines to a pointer to the first element.
You can play around with this code:
#include <stdio.h>
#include <string.h>
void analyse_inst(char* mnemonic, char* operands);
int main()
{
char mnemonic[] = "add";
char operands[] = "five to two";
analyse_inst(mnemonic, operands);
printf("%s\n", mnemonic);
}
void analyse_inst(char* mnemonic, char* operands)
{
printf("%s ", mnemonic);
printf("%s\n", operands);
strcpy(mnemonic, "hi");
}
When you write something like char *mnemonic that means you are creating a pointer variable (variable that will hold the address of another variable) but since the data type of the mnemonic is char it will hold the address of variable with char datatype only.
Now, inside your code you have written mnemonic = "add" so here "add" is the string that is array of characters and mnemonic is pointing to the base address of that array.
and while calling the function you are passing the references of these char arrays, so you need to change void analyse_inst(char mnemonic, char operands) to void analyse_inst(char *mnemonic, char *operands) to get the references in these respective pointer variables. Reason is same We need pointer variables to hold the references.
And the & returns the address of the variable, that means the reference to the memory location in which the variable is stored.
Hope this will help.
Strings in C are stored as arrays of characters, terminated by a character with the value '\0' ("NIL"). You cannot directly pass around arrays, so instead a pointer to the first character is used, which is why you must pass char *s to the function in order to access strings.
A character is typically much smaller than a pointer (think 8 vs 32/64 bits), so you cannot squeeze a pointer value into a single character.
C does not have pass by reference; it's pass by value only. Sometimes that value is as close to a reference as the language can come (i.e. a pointer), but then that pointer is in turn passed by value.
Consider this:
static void put_next(const char *s)
{
putchar(*s++);
}
int main(void)
{
const char *string = "hello";
put_next(string);
put_next(string);
}
This will print hh, since it's being passed the same value string every time, the fact that s, which is a different variable holding a copy of the same value, is incremented inside the function doesn't matter. The incremented value is local to the function, and thrown away once it goes out of scope.
I will discuss things in the context of your code, but I want to get some basics out of the way first.
In a declaration, the unary * operator indicates that the thing being declared has pointer type:
T *p; // for any type T, p has type "pointer to T"
T *p[N]; // for any type T, p has type "N-element array of pointer to T"
T (*p)[N]; // for any type T, p has type "pointer to N-element array of T"
T *f(); // for any type T, f has type "function returning pointer to T"
T (*f)(); // for any type T, f has type "pointer to function returning T"
The unary * operator has lower precedence then the postfix [] subscript and () function operators, so if you want a pointer to an array or a function, the * must be explicitly grouped with the identifier.
In an expression, the unary * operator dereferences the pointer, allowing us to access the pointed-to object or function:
int x;
int *p;
p = &x; // assign the address of x to p
*p = 10; // assigns 10 to x via p - int = int
After the above code has executed, the following are true:
p == &x // int * == int *
*p == x == 10 // int == int == int
The expressions p and &x have type int * (pointer to int), and their value is the (virtual) address of x. The expressions *p and x have type int, and their value is 10.
A valid1 object pointer value is obtained in one of three ways (function pointers are also a thing, but we won't get into them here):
using the unary & operator on an lvalue2 (p = &x;);
allocating dynamic memory via malloc(), calloc(), or realloc();
and, what is relevant for your code, using an array expression without a & or sizeof operator.
Except when it is the operand of the sizeof or unary & operator, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" is converted ("decays") to an expression of type "pointer to T", and the value of the expression is the address of the first element of the array3. So, if you create an array like
int a[10];
and pass that array expression as an argument to a function like
foo( a );
then before the function is called, the expression a is converted from type "10-element array of int" to "pointer to int", and the value of a is the address of a[0]. So what the function actually receives is a pointer value, not an array:
void foo( int *a ) { ... }
String literals like "add" and "five to two" are array expressions - "add" has type "4-element array of char" and "five to two" has type "12-element array of char" (an N-character string requires at least N+1 elements to store because of the string terminator).
In the statements
mnemonic = "add";
operands = "five to two";
neither string literal is the operand of the sizeof or unary & operators, and they're not being used to initialize a character array in a declaration, so both expressions are converted to type char * and their values are the addresses of the first element of each array. Both mnemonic and operands are declared as char *, so this is fine.
Since the types of mnemonic and operands are both char *, when you call
analyse_inst( mnemonic, operands );
the types of the function's formal arguments must also be char *:
void analyse_inst( char *mnemonic, char *operands )
{
...
}
As far as the "pass by reference" bit...
C passes all function arguments by value. That means the formal argument in the function definition is a different object in memory from the actual argument in the function call, and any changes made to the formal argument are not reflected in the actual argument. Suppose we write a swap function as:
int swap( int a, int b )
{
int tmp = a;
a = b;
b = tmp;
}
int main( void )
{
int x = 2;
int y = 3;
printf( "before swap: x = %d, y = %d\n", x, y );
swap( x, y );
printf( "after swap: x = %d, y = %d\n", x, y );
...
}
If you compile and run this code, you'll see that the values of x and y don't change after the call to swap - the changes to a and b had no effect on x and y, because they're different objects in memory.
In order for the swap function to work, we have to pass pointers to x and y:
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
...
swap( &x, &y );
...
}
In this case, the expressions *a and *b in swap refer to the same objects as the expressions x and y in main, so the changes to *a and *b are reflected in x and y:
a == &x, b == &y
*a == x, *b == y
So, in general:
void foo( T *ptr ) // for any non-array type T
{
*ptr = new_value(); // write a new value to the object `ptr` points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
This is also true for pointer types - replace T with a pointer type P *, and we get the following:
void foo( P **ptr ) // for any non-array type T
{
*ptr = new_value(); // write a new value to the object `ptr` points to
}
void bar( void )
{
P *var;
foo( &var ); // write a new value to var
}
In this case, var stores a pointer value. If we want to write a new pointer value to var through foo, then we must still pass a pointer to var as the argument. Since var has type P *, then the expression &var has type P **.
A pointer value is valid if it points to an object within that object's lifetime.
An lvalue is an expression that refers to an object such that the object's value may be read or modified.
Believe it or not there is a good reason for this rule, but it means that array expressions lose their "array-ness" under most circumstances, leading to much confusion among people first learning the language.
This question already has answers here:
What exactly is meant by "de-referencing a NULL pointer"?
(8 answers)
Closed 5 years ago.
I am studying C at school , and I am facing a problem with pointers , Why does this unhandled error rise (im using visual studio 2013 express for desktop on 64 bit windows 10) , when I try to run the code below.
My question is , Why is this happening?
Code Block :
// ~~ Libraries Or Header Files. ~~ //
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ~~ Main Function ~~ //
int main(void)
{
// ~ Variables ~ //
int * p = NULL;//#define NULL ((void *)0)
printf(*p);
//printf(p)l also raises an error.
// ~ END ~ //
system("PAUSE");
return 0;
}
Error:
" Unhandled exception at 0x009A3C2A in hwQ3.exe: 0xC0000005: Access violation
reading location 0x00000000 ".
There are two problems with this code.
First, printf expects its first argument to be a format string, and the type of the argument is assumed to be const char * (it's a pointer to the first character in a zero-terminated string). Since the object p has type int *, the expression *p has type int, so it's the wrong type, and the value of *p isn't a valid address of a string, because...
You've initialized p to NULL. NULL is an invalid pointer value that's guaranteed to compare unequal to any valid pointer value (it's a well-defined "nowhere" value). When you write *p, you're saying, "I want the value of the integer object p points to." Since p points "nowhere", the behavior of the operation is undefined, and one possible result of undefined behavior is a segfault.
So...
If you want to print the value of the integer object that p points to, you would write something like
printf( "%d\n", *p );
but only after you do a sanity check on p to make sure it isn't NULL:
if ( p ) // or p != NULL
printf( "%d\n", *p );
Valid pointer values are obtained by one of the following methods:
Using the unary & operator on an lvalue (an expression that refers to an object in memory such that the object may be read or updated):
p = &x; // x is an integer object
p = &a[i]; // a is an array of integer, so a[i] is an integer object
p = &foo.bar; // foo is a struct with an int member named bar, so foo.bar is an integer object
etc.
Calling one of malloc, calloc, or realloc:
p = malloc( sizeof *p );
Using an array expression in most circumstances. Unless it is the operand of the sizeof or unary & operators, or is a string literal being used to intialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. In the case of printf, when we write
printf( "this is a test\n" );
the type of the string literal "this is a test\n" is converted from type "16-element array of char" to "pointer to char", and its value is the address of the first character in the string - that address value is what actually gets passed to printf.
The first argument to printf(...) is a const char *format so in both cases you're trying to dereference a NULL pointer. That causes you to access memory outside your allowable range (at zero).
Basic information about pointers:
Pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this:
int *ip;
Pointers are generated with the address-of'' operator &, which we can also think of as thepointer-to'' operator. Demonstrating this by declaring (and initializing) an int variable i, and then setting ip to point to it:
int i = 5;
ip = &i;
Example pointer usage:
#include <stdio.h>
int main(){
int var =10;
int *ptr = &var;
printf("%d\n", *ptr);
return 0;
}
What happens when you deference the pointer to NULL?
int *a = NULL; // a is a null pointer
int b = *a; // CRASH: dereferencing a, trying to read it
*a = 0; // CRASH: dereferencing b, trying to write it
Consider the program,
#include <stdio.h>
int main(){
int a[][4] = {2,3,4,5,
43,32,76,3
};
int *p;
int (*q)[4];
p = (int *)a;
q = a;
printf("%u\t%u", (unsigned int)p,(unsigned int)q);
printf("\n%d\t%d",*(++p),*(++q));
return 0;
}
In the above program, I have defined two pointers,
1) Integer pointer
2) Pointer to an Array
When compiled using the GCC compiler, I met with two doubts,
Question 1:
Why is that, the statement,
printf("\n%d\t%d",*(++p),*(++q));
returns an address when I try to dereference (++q)?
Question 2:
Is there any way I can use a "Pointer to an array" variable('q' - in this program) to access the consecutive element in a row?
Compiler: GCC; OS: Ubuntu
*(++q) does not "return an address". It returns a result of type int[4], which is an lvalue of array type. That lvalue refers to a[1] subarray of array a.
This means that the title of your question is no accurate at all: the dereference operator in this case does return exactly what it is supposed to return. The pointer is declared as a pointer to an array, and the dereference operator evaluates to an lvalue of array type.
However, immediately after that you use that array lvalue in a context where it decays to pointer type, just like any other array would (see What is array decaying?, Why do arrays in C decay to pointers?). Passing an array as an argument to printf happens to be such a context. So, that original array lvalue decays to a pointer. That pointer value points to the beginning of a[1], which is the same as &a[1][0]. That pointer value is passed to printf and you attempt to print it with %d.
(Note that using %d in printf to print pointer values triggers undefined behavior.)
Well, you can access them in any way you wish
q = a;
q[1][1] = 42; // accesses `a[1][1]`
++q;
(*q)[2] = 5; // accesses `a[1][2]`
This declaration
int (*q)[4];
declares a pointer to objects of type int[4]. To simplify the understanding you could introduce a typedef the following way
typedef int T[4];
T *q;
q = a;
So dereferencing the pointer you will get the pointed object of the type T that represents an array of type int[4]. As result using this object in the printf function
printf("\n%d\t%d",*(++p),*(++q));
^^^^^
you will get the second "row" (due to incrementing the pointer ++q) of the array a that is in turn a one-dimensional array of type int[4] that in turn is implicitly converted to pointer to its first element.
Thus the expression *(++q) has the type int * and points to the first element of the second "row" of the array a.
If you want to use this pointer to traverse the elements of the array a you can do it the following way
#include <stdio.h>
int main(void)
{
int a[][4] = { { 2, 3, 4, 5 }, { 43, 32, 76, 3 } };
int ( *q )[4] = a;
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
for ( size_t j = 0; j < sizeof( *q ) / sizeof( **q ); j++ )
{
printf( "%2d ", q[i][j] );
}
printf( "\n" );
}
return 0;
}
The program output is
2 3 4 5
43 32 76 3
That is q[0] is the first "row" of the array a. You can write also just *q. q[1] is the second "row" of the array a. You may can write also like *( q + 1 ). To get access to the elements of each row you can apply the subscript operator like (the first row)
q[0][i] where i is some index value. Or you can write the same like ( *q )[i]
and like (the second row) q[1][i] or ( *( q + 1 ) )[i]
And the special expression like **q yields the first element of the first row of the array a.
TL;DR answer, dereferencing a pointer-to-an array produces an array, which, once passed as a function argument, decays to pointer to the first element of the array. So, the final value is of pointer type (the former and the later are of pointer to different type, but they are pointers, nonetheless).
That said, first of all
printf("%u\t%u", (unsigned int)p,(unsigned int)q);
is implementation dependent behaviour as conversion of a pointer to an integer is implementation defined. If at all, you can cast the pointer to uintptr_t type and print using PRIuPTR format specifier to print the value.
Secondly, pointer arithmetic honors the data type. q is a pointer to an array of 4 ints. Once incremented, it points past the first array. But then, there's a mismatch in the supplied format specifier.
printf("\n%d\t%d",*(++p),*(++q));
^^ ^^^^^^
To elaborate, q is of type pointer-to-array. Dereferencing that produces an array, now once the array is passed as an argument to a function, it decays to the pointer to the first element of the array. So, essentially, you're passing a pointer as the argument to %d format specifier, which is the mismatch, leading to undefined behavior.
Finally, regarding the access to individual elements, you can either use
(*(q+m))[n] --> First dereference q to obtain the array, then use indexing
q[m][n] --> q[m] produces the array, then n is used as indexing to get individual element.
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").
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.