question about second pointers - c++

i am using c++ and i have some trouble about pointers
i know that if we declare some variable
int t=7;
int *p=&t;
*p gives adress of variable t but in c++ here also definition of **s why it is used ?i have read it but i have some misunderstanding please can anybody give me example how use?let take about given example

Its a pointer to a pointer.
For example, if your operation was in a function:
void make_p(int **p, int *t) {
*p = t;
}
int main() {
int *p;
int t;
make_p(&p, &t);
}

For example, you can use this for creating an object in a function:
void create( Type** result )
{
*result = new Type();
}
//somewhere else in code
Type* object;
create( &object );
this doesn't make much sence for void functions creating a single object, but in case the function needs some predefined return type or needs to create more than one object that will make sence. A classic example is IUnknown::QueryInterface() that must return HRESULT:
HRESULT CYourClass::QueryInterface( IID& iid, void** result )
{
//inside you need to decide whether you know the iid passed, copy a pointer
// into *ppv and then return apropriate HRESULT
}

First of all *p will give you the value of variable t and not the address of t. Only 'p' will give you the address of t.
Essentially every address is just an integer number. If you are compiling for 32-bit architecture then it will be 32-bit long number and if you are compiling for 64-bit then it will be 64-bit long. This means that you can use a simple integer variable to store any variable's address irrespective of what type the variable is but it is better to use a proper type of pointer to store the variable's address. This way we can dereference the pointer and we dont have have to type cast it whenever we want to use the variable which is being pointed to.
To create a pointer to some variable, we declare a variable of the same type but put a '*' in front of the variable's name. For example you can declare an integer as follows
int a;
To create a pointer to 'a', create a new variable with the same type as a and just put a '*' in front of it. So the declaration of pointer to the above variable 'a' will look like
int *p;
Notice that other than an additional '*', its the same declaration. Now 'p' is a pointer to an integer variable.
Now consider that you want another pointer to point to this variable 'p'. Again you declare a variable similar to 'p' and just put a '*' in front of it. So a declaration of pointer to the above variable will look some thing like
int **pp;
Again notice that other than an extra '*' this declaration is very same to the declaration of 'p'. So the variable 'pp' is a pointer to a pointer to an integer
You can declare a pointer to 'pp' in the same way and the cycle will continue. This is also true for non simple types i.e pointers to variables of class or structure types are created the same way.

It's so we can change where other pointers are pointing to. Pointer to a pointer. Consider the following:
int *p1 = &j; // j is a int.
int *p2 = &k; // k is an int.
int **p;
p = &p1; //p points at p1.
*p = p2; //p1 now points to j because p2 is pointing to j.
//Also we can do this through just plain old variables.
int l;
*p = &l; //p1 is now pointing at l

Just as int *p; defines a pointer to an int, int **s; defines a pointer to (a pointer to an int). This comes up usually in two cases:
First, if you want an array that holds pointers to an int, you would do something like: int **arr = malloc(sizeof(int*) * arr_size);
Second, when a function needs to return more than one value, it's common to have the extra values returned by reference. I.e.:
/* Return x, y and error code. */
int getVals(int *px, int *py) {
*px = x;
*py = y;
return 0;
}
/* Return new object and error code. */
int newFoo(struct Foo **out_foo) {
struct Foo *f = malloc(sizeof(struct Foo));
f->value = 0;
*out_foo = f;
return 0;
}

Related

What exactly is the purpose of the (asterisk) in pointers?

I'm new to programming and I'm trying to wrap my head around the idea of 'pointers'.
int main()
{
int x = 5;
int *pointerToInteger = & x;
cout<<pointerToInteger;
}
Why is it that when I cout << pointerToInteger; the output is a hexdecimal value, BUT when I use cout << *pointerToInteger; the output is 5 ( x=5).
* has different meaning depending on the context.
Declaration of a pointer
int* ap; // It defines ap to be a pointer to an int.
void foo(int* p); // Declares function foo.
// foo expects a pointer to an int as an argument.
Dereference a pointer in an expression.
int i = 0;
int* ap = &i; // ap points to i
*ap = 10; // Indirectly sets the value of i to 10
A multiplication operator.
int i = 10*20; // Needs no explanation.
One way to look at it, is that the variable in your source/code, say
int a=0;
Makes the 'int a' refer to a value in memory, 0. If we make a new variable, this time a (potentially smaller) "int pointer", int *, and have it point to the &a (address of a)
int*p_a=&a; //(`p_a` meaning pointer to `a` see Hungarian notation)
Hungarian notation wiki
we get p_a that points to what the value &a is. Your talking about what is at the address of a now tho, and the *p_a is a pointer to whatever is at the &a (address of a).
This has uses when you want to modify a value in memory, without creating a duplicate container.
p_a itself has a footprint in memory however (potentially smaller than a itself) and when you cout<<p_a<<endl; you will write whatever the pointer address is, not whats there. *p_a however will be &a.
p_a is normally smaller than a itself, since its just a pointer to memory and not the value itself. Does that make sense? A vector of pointers will be easier to manage than a vector of values, but they will do the same thing in many regards.
If you declare a variable of some type, then you can also declare another variable pointing to it.
For example:
int a;
int* b = &a;
So in essence, for each basic type, we also have a corresponding pointer type.
For example: short and short*.
There are two ways to "look at" variable b (that's what probably confuses most beginners):
You can consider b as a variable of type int*.
You can consider *b as a variable of type int.
Hence, some people would declare int* b, whereas others would declare int *b.
But the fact of the matter is that these two declarations are identical (the spaces are meaningless).
You can use either b as a pointer to an integer value, or *b as the actual pointed integer value.
You can get (read) the pointed value: int c = *b.
And you can set (write) the pointed value: *b = 5.
A pointer can point to any memory address, and not only to the address of some variable that you have previously declared. However, you must be careful when using pointers in order to get or set the value located at the pointed memory address.
For example:
int* a = (int*)0x8000000;
Here, we have variable a pointing to memory address 0x8000000.
If this memory address is not mapped within the memory space of your program, then any read or write operation using *a will most likely cause your program to crash, due to a memory access violation.
You can safely change the value of a, but you should be very careful changing the value of *a.
yes the asterisk * have different meanings while declaring a pointer variable and while accessing data through pointer variable. for e.g
int input = 7;
int *i_ptr = &input;/*Here * indicates that i_ptr is a pointer variable
Also address is assigned to i_ptr, not to *iptr*/
cout<<*i_ptr;/* now this * is fetch the data from assigned address */
cout<<i_ptr;/*it prints address */
for e.g if you declare like int *ptr = 7; its wrong(not an error) as pointers ptr expects valid address but you provided constant(7). upto declaration it's okay but when you go for dereferencing it like *ptr it gives problem because it doesn't know what is that data/value at 7 location. So Its always advisable to assign pointers variable with valid addresses. for e.g
int input = 7;
int *i_ptr = &input;
cout<<*i_ptr;
for example
char *ptr = "Hello"; => here * is just to inform the compiler that ptr is a pointer variable not normal one &
Hello is a char array i.e valid address, so this syntax is okay. Now you can do
if(*ptr == 'H') {
/*....*/
}
else {
/*.... */
}

reassign pointer gives error

I am new to C++ , therefore please forgive me if my question seems basic, I am not able to reassign a pointer when I use the star, here is my code:
int val = 8;
int number = 23;
int *pointer = &val;
*pointer = &number; //<-- error
this gives an error: assign to int from incompatible type int. here is what I tried:
pointer = &number; // this works
therefore my question is, why is this wrong: *pointer = &number
In your code,
*pointer = &number; //<-- error
by saying *pointer, you're dereferencing the pointer, which is of type int, then you try to assign a pointer type value to it, which is not correct.
What you want to do, is to assign the address of a variable and to hold that, you want the pointer variable itself to be on the LHS of the assignment. So,
pointer = &number;
is the correct way to go.
The reason this results in an error is because you misunderstood the type of each variable.
int val = 8; // type of `val` is int
int number = 23; // type of `number` is an int
int *pointer = &val; // type of `pointer` is an int *
*pointer = &number; // type of `pointer` is int *, so type of `*pointer` is int
It doesn't work because *pointer dereferences the pointer, so you're assigning an address to a pointer, which is not what you want.
When you say
int *pointer
the * indicates that you are creating a pointer, you can think of the * as part of the data type. i.e. it's a pointer to an integer type. To reference the pointer itself (the type that stores an address in memory), you simply use the name of the pointer, just like a regular variable.
When you add the * infront, you are dereferencing the pointer. Meaning, you are accessing whatever is stored at the memory address that the pointer is pointing to, in this case an int.
Basically, pointer gives you an address in memory, *pointer gives you the int stored at that address.
int *pointer = &val;
Breaking this up actually means
int* pointer;
pointer = &val;
When you derefrence an integer pointer it becomes just an integer.When you add & to a non-pointer it becomes a pointer.So doing
is bad,because *ptr is not a pointer and &i is a pointer
int n = 0;
int *ptr = &n //good,because they are both pointers
int i = 0;
*ptr = &i //bad because only one is a pointer

Why do variable pointers contain the address of the same data type?

General syntax of pointer declaration: data-type *pointer_name;
A pointer is a variable whose value is the address of another variable, i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before you can use it to store any variable address. The data type of pointer must be same as the variable, which the pointer is pointing.
Why is it important that a pointer variable should contain the address of a variable of the same data type?
As a pointer has nothing to do with the value of another variable, why can't an integer pointer have the address of float data type variable?
Correct form:
int a = 10 ;
int *ptr = &a ;
ERROR, type mismatch
float a;
int *ptr; ptr = &a;
Because when you increase a pointer like
ptr++;
it will point to an address that is one multiplied with the size of the data type. If you do
ptr+=2;
and the data type is occupying 4 bytes which would be the case if the pointer was declared as
float *ptr;
the pointer will increase with 8 byte positions.
Before answering that, let me ask you, if it were valid, what would you do with such a pointer?
Suppose you have (inside a function)
float a;
int *ptr; ptr = &a;
*p = 1;
++*p;
return *p;
In such a case, there is no reason at all not to just use an int variable if it's an int you want.
Suppose you have (inside a function)
float a;
int *ptr; ptr = &a;
a = 3.14;
++*p;
return a;
In this sort of object aliasing, there can be a use, but allowing constructions like this is a pain for compilers. Compilers are free to assume, and some do assume, that the modification of *p has no effect on the value of a, so still return 3.14 unmodified;
If the latter case is something you're looking for, you can use union, which both makes your code clearer to other readers, and makes your code clearer to the compiler:
union {
float f;
int i;
} u;
u.f = 3.14;
++u.i;
return u.f;
So, to answer: it's to prevent you from shooting yourself in the foot. It's not allowed because there is no way such a pointer is useful. The one case where it could be useful is actually a case where it doesn't work, and there is another language construct that does handle it, and handles it correctly.
There is also the simple matter of dereferencing the pointer.
something = *pointer;
How much data should be read when the pointer is dereferenced? The compiler must know the data type in order to perform operations on the data like fetch, add, etc.
It's a safety feature. A pointer of one type pointing to a variable of another is a recipe for disaster; it has almost no legitimate purpose and almost anything you do with it is dangerous, especially if the types are of different sizes.
You can override this feature by means of casting. If you do so, you can no longer claim that you didn't know you were doing something dangerous.
It is possible for pointers to point to any data type: that's exactly what void pointers are for. You can use a void * to point to any data type1, and then you can get the original pointer back.
float f = 1.0f;
int i = 12;
void *p = &f;
p = &i;
Of course, you can't dereference a void pointer without first casting it back to the correct pointer type. It is up to you to ensure that the pointer type is correct.
// In C, this is valid: implicit conversions to void * and back.
float f = 1.0f;
void *p = &f;
float *fp = p;
printf("*fp = %f\n", *fp);
// In C++, you have to use a cast:
float *fp = static_cast<float *>(p);
Void pointers have limitations: you cannot dereference them, and you cannot do any pointer arithmetic.
1: Function pointers should not be cast to void *.
Lets understand it with an example.
int main()
{
char i = 8;
int *ptr = &i;
printf("Value of i = %d", *ptr);
return 0;
}
Ans: It will print some garbage because it dereferenced 4 byte in memory.
so if you do char *ptr = &i;, it will dereference 1 byte and so on..
It will give correct answer.

Changing constant pointer's address

I'm trying to understand one thing.
I know I can't change constant pointer's value, but I can change its address, if I initialize a pointer the following way:
int foo = 3;
const int *ptr = &foo;
*ptr = 6; // throws an error
int bar = 0;
ptr = &bar; // foo == 0
Now, let's say I declare (/define, I never remember which one) a function:
void change(const int arr[], int size);
int main() {
int foo[2] = {};
change(foo, 2);
std::cout << foo[0];
}
void change(const int arr[], int size) {
// arr[0] = 5 - throws an error
int bar = 5;
arr = &bar;
}
The last line in the code above doesn't throw any errors. However, when the function is over and I display the first element, it shows 0 - so nothing has changed.
Why is that so?
In both situations I have constant pointers, and I try to change its address. In the first example it works. In the second one it doesn't.
I also have another question. I've been told that if I want to pass two-pointers type to the function, const keyword won't work as expected. Is that true? And if so, then what's the reason?
You're screwing up the terminology a lot, so I'm going to start there because I think it is a major cause of your confusion. Consider:
int x;
int* p = &x;
x is an int and p is a "pointer to int". To modify the value of p means to change p itself to point somewhere else. A pointers value is the address it holds. This pointer p holds an address of an int object. To change the pointer's value doesn't mean to change the int object. For example, p = 0; would be modifying p's value.
In addition to that, the address of p is not the address it holds. The address of p would be what you get if you did &p and would be of type "pointer to pointer to int". That is, the address of p is where you would find the pointer p in memory. Since an object doesn't move around in memory, there's no such thing as "changing its address".
So now that's out of the way, let's understand what a constant pointer is. const int* is not a constant pointer. It's a pointer to a constant object. The object it points to is constant, not the pointer itself. A constant pointer type would look more like int* const. Here the const applies to the pointer, so it is of type "const pointer to int".
Okay, now I'll quickly give you an easy way to remember the difference between declaration and definition. If you bought a dictionary and all it had was a list of words in it, would you really call it a dictionary? No, a dictionary is supposed to filled with definitions of words. It should tell you what those words mean. The dictionary with no definition is only declaring that such words exist in the given language. So a declaration says that something exists, and a definition gives the meaning of it. In your case:
// Declaration
void change(const int arr[], int size);
// Definition
void change(const int arr[], int size) {
// arr[0] = 5 - throws an error
int bar = 5;
arr = &bar;
}
Now to explain the issue here. There's no such thing as an array argument type. Any array type argument is converted to a pointer. So the declaration of change is actually identical to:
void change(const int arr*, int size);
when you do arr = &bar; you are simply assigning the address of bar to the pointer arr. That has no effect on the array elements that arr is pointing to. Why should it? You are simply changing where arr points to, not the objects it points at. And in fact you can't change the objects it points at because they are const ints.
I know I can't change constant pointer's value, but I can change its address
Nah. You can't change the address of anything. Did you mean that you can't change the object it points to, but you can change the pointer itself? Because that's what is the truth - in the case of a pointer-to-const type. However, if you have a const pointer to a non-const object, then you can't change the pointer, you can only change whatever it points to.
Addendum (edit): a handy rule of thumb is that const applies to what stands on its left side, except when nothing stands on its left side, because then it applies to the type that is on its right side. Examples:
const int *ptr;
int const *ptr; // these two are equivalent: non-const pointer to const int
int *const ptr; // const pointer to non-const int
int const *const ptr; // const pointer to const int
const int *const ptr; // same as above
However, when the function is over and I display the first element, it shows 0 - so nothing has changed.
Scope. arr is a function argument - so it's local to the function. Whatever you do with it, it won't be effective outside of the function. To achieve what you want, declare it as a reference:
void change(const int *&arr, int size)
I've been told that if I want to pass two-pointers type to the function, const keyword won't work as expected. Is that true?
This depends on what your expectations are. If you read the standard attentively and have proper expectations, then it will indeed work as expected. Examples:
const int **ptr; // pointer to pointer to const int
int const **ptr; // same as above
const int *const *ptr; // pointer to const pointer to const int
etc. You can generate more of these funky declarations using CDecl
The first thing is using the proper terms, which actually helps in understanding:
const int *ptr = &foo;
That is a pointer to a constant integer, not a constant pointer to an integer. You cannot change the object pointed, but you can change the pointer to refer to a different object.
void change(const int arr[], int size);
That signature is processed by the compiler as void change( const int *arr, int size ), and I'd recommend that you type it as that, as it will reduce confusions. Where the function is called, change(foo,2), the compiler will transform the argument foo (type is int[2]) to &foo[0] which has type const int* (both transformations are commonly called decay of the array to a pointer).
Now as in the first block of code, you cannot change the pointed memory, but you can change the pointer to refer to a different object.
Additionally, in C++ the default mode is pass-by-value. The pointer arr inside change is a copy of the value &foo[0]. Inside the function you are changing that copy, but that will not affect anything outside of the function context.
const int * is doing what it's supposed to do, what's confusing you is its purpose.
Think of it as a pointer to a readonly int. You can point to any int you want, but it's going to be readonly no matter what.
You might use this to loop through an array of type const int, for example.

What does '**' mean in C?

What does it mean when an object has two asterisks at the beginning?
**variable
In a declaration, it means it's a pointer to a pointer:
int **x; // declare x as a pointer to a pointer to an int
When using it, it deferences it twice:
int x = 1;
int *y = &x; // declare y as a pointer to x
int **z = &y; // declare z as a pointer to y
**z = 2; // sets the thing pointed to (the thing pointed to by z) to 2
// i.e., sets x to 2
It is pointer to pointer.
For more details you can check: Pointer to pointer
It can be good, for example, for dynamically allocating multidimensional arrays:
Like:
#include <stdlib.h>
int **array;
array = malloc(nrows * sizeof(int *));
if(array == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
for(i = 0; i < nrows; i++)
{
array[i] = malloc(ncolumns * sizeof(int));
if(array[i] == NULL)
{
fprintf(stderr, "out of memory\n");
exit or return
}
}
It means that the variable is a pointer to a pointer.
Pointer to a pointer when declaring the variable.
Double pointer de-reference when used outside the declaration.
Pointer to a pointer.
You can use cdecl to explain C-types.
There's an online interface here: http://cdecl.org/. Enter "int **x" into the text field and check the result.
**variable is double dereference. If variable is an address of an address, the resulting expression will be the lvalue at the address stored in *variable.
It can mean different things if it's a part of declaration:
type **variable would mean, on the other hand, a pointer to a pointer, that is, a variable that can hold address of another variable, which is also a pointer, but this time to a variable of type 'type'
It means that the variable is dereferenced twice. Assume you have a pointer to a pointer to char like this:
char** variable = ...;
If you want to access the value this pointer is pointing to, you have to dereference it twice:
**variable
It is a pointer to a pointer. You can use this if you want to point to an array, or a const char * (string). Also, in Objective-C with Cocoa this is often used to point to an NSError*.
Pointer to another pointer
** is a pointer to a pointer. These are sometimes used for arrays of strings.
It's a pointer to pointer.
As in if *x means that it will contain an address of some variable then if i say
m=&x then m is shown as
int **m