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

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 {
/*.... */
}

Related

What is the difference between a pointer set to a value and a pointer set to the address of a value?

I've got two questions, really. The first has to do with the interaction between a pointer and a variable, and the second has to do with the interaction between a pointer and an array. What is the best way to understand this?
I understand that a pointer contains the address to a variable, but I'm not sure what the difference is between setting the pointer to an address and setting the pointer to a variable.
I seem to have the same problem with an array, except more complex because an array may not just have one value.
For instance:
int num = 5;
int * p;
p = num; //This results in an error
p = &num; //This does not
Whereas:
int num[2] = {5, 10};
p = num; //This does not result in an error
p = &num; //This does
For the first situation, I get an error saying, "a value of type "int" cannot be assigned to an entity of type "int *"".
For the second situation, I get an error saying, "a value of type "int (*)[2]" cannot be assigned to an entity of type "int *"".
Why is this?
EDIT: I don't believe this to be a duplicate question. Array decaying does not answer my question at all, and instead this has to do with pointer types rather than properties of arrays. This question has been answered well already, but I would like to clarify that my issue was not answered by anything having to do with array decaying.
A variable has a number of distinct properties.
Given your variable definition, which I quote here
int num = 5;
its type is int, its name is num, it is initialised with a value of 5, and its address (e.g. location in machine memory) is &num.
If I was to define a second variable immediately after
int q = 5
then this variable would (like num) have type int, and value 5, but a different name q and a different address in memory &q. Even though they have the same value, the addresses of num and q are different. That (among other things) ensures that assigning q = 6 does not change the value of num.
It goes further. The pointer in your sample
int * p;
means that p is a pointer to an int. It has type int *, so its value can be the address of an int. So the assignment
p = num; //This results in an error
doesn't work, because p has type int * and num has type int. The two types are distinct, and an int cannot be converted implicitly to an int *, so the assignment is not allowed. They are different types. In the real world, the street address of a house is something different from a house, even if there is an association between them.
However your assignment
p = &num; //This does not
works, because p is of type int * and &num is the address of an int so also has type int *.
However, with arrays, the rules are a little different.
int num[2] = {5, 10};
p = num; //This does not result in an error
p = &num; //This does
Firstly, num is an array of two int. It has name num, but its type is int[2], and its value is actually based on the pair of ints 5 and 10.
When used in an expression, num is converted to a pointer to its first element. So
p = num;
is equivalent to
p = &num[0];
The conversion of num to &num[0] is called an "array to pointer" conversion.
The second assignment you tried
p = &num; //This does
is different. In this case &num is the address of the array num, not the address of its first element. So &num has type int (*)[2] which (in C++) syntactically means "pointer to an array of two int".
The type of p is int * (because that's how you defined it) whereas &num gies a result with type int (*)[2]. Those types are different, so the assignment is invalid.
If you want a variable that points to an array of two int (as distinct from your p which can point at the first element of an array of int) then define
int num[2] = {5,10};
int (*q)[2]; // q has type int (*)[2]
q = num; // this will work
Then you can do, for example;
std::cout << (*q)[0] << ' ' << (*q)[1] << '\n';
to print the values 5 and 10. This works because q points at the array, *q is (a reference to) the array num, so (*q)[0] and (*q)[1] access num[0] and num[1] respectively.
Note that the parentheses () are critical in all of the above discussion. *q[0] is actually (by rules of operator precedence and associativity) equivalent to *(q[0]) which is something quite different from (*q)[0]. I'll leave working out what *(q[0]) is (or is not) an exercise.
Pointers are a big hurdle to come across for new programmers.
Let me try to put it in the most easiest way I can.
Pointers are a data type in languages like C and C++ which point to a specific "memory location" specified by the pointer's type, meaning only a int pointer can point to a int memory location.
In your first example,
p = num
gives an error because you are trying to point the pointer to a value, but pointers cannot point to values but instead only memory locations. That is why
p = &num
works.
In your second example,
p = num
works because for arrays and structs in c and c++, setting the pointer directly to them automatically points to the first memory address specified by the array.
Arrays are not special data types by themselves but rather sequences of values right after one another in memory.
But,
p = &num
doesn't work because you are trying to point to the memory location of a memory location. num already points to the first location in the array, and &num points to the memory location of that location. That is why it's an error.
Hope you got it!

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.

address of a pointer variable

I'm currently learning c language, and I bumped into this code. ptr is already a pointer type of variable, so what is the effect of the & operator on it, cause I know that usually the operator uses to get the address of non-pointer variable.
struct name {
int a; float b; char c[30];
};
int main()
{
struct name *ptr;
int i,n;
printf("Enter n: ");
scanf("%d",&n);
ptr = (struct name*)malloc(n*sizeof(struct name));
/* Above statement allocates the memory for n structures with pointer ptr pointing to base address */
for(i=0; i<n; ++i) {
printf("Enter string, integer and floating number respectively:\n");
scanf("%s%d%f", &(ptr+i)->c, &(ptr+i)->a, &(ptr+i)->b);
}
}
&(ptr + i)->c
this takes the address of the variable c stored at the ith element of ptr. So your first intuition was correct.
ptr+i
is simply the pointer arithmatic to find the ith element fo the array.
(ptr+i)->c
accesses the field c from that struct, and the & takes the address of that variable.
The code &(ptr + i)->c gives you the address of the struct element c that belongs to the ith struct in your list. Let's break it down a bit.
(ptr + i) is pointer arithmetic. It adds i to the address stored at ptr.
(ptr + i)->c accesses the struct element c through the pointer (ptr + i).
&(ptr + i)->c takes the address of the struct element c through the pointer (ptr + i).
Also, I know this isn't quite doing what you thought it was doing, since you thought the address-of operator applied to the pointer, but just an FYI: you can indeed take the address of a pointer. Such a construct is a pointer to a pointer, and is useful when you want to change the pointer (not just the value stored at the address it points to) in a function. e.g.
int a = 5; /* regular variable */
int* pa = &a; /* pointer to a */
int** ppa = &pa; /* pointer to pointer (which points to a) */
Firstly, operator & in C and C++ languages is used to get address of any variable. More precisely, it can be used to get address of [almost] any lvalue (there are some differences between C and C++ in that regard). Pointer variables are ordinary variables. There's nothing special about them, which means that there's nothing unusual in seeing operator & applied to pointers.
Secondly, in the code you provided, there actually isn't a single instance of & being applied to a pointer. There are four applications of & in your code
&n
&(ptr+i)->a
&(ptr+i)->b
&(ptr+i)->c
In the first two cases it is applied to int objects. In the thirds case it is applied to float object. In that last case it is applied to a char [30] object. No pointers.
struct name* ptr;
This creates a pointer to a name.
struct name** p = &ptr;
This creates a pointer to a pointer to a name by taking the address of the pointer you already created.
In your case, you are passing in pointers to scanf, and have a dynamic array of name, so
&(ptr + i)->c
finds the ith element of the array, and returns the address of its c member to scanf (same with a and b).
Passing in the address of the pointer allows for that pointer to be changed (e.g. reallocated). In C++, it would be virtually identical to passing by reference.

Assigning int value to an address

I thought the following codes were correct but it is not working.
int x, *ra;
&ra = x;
and
int x, ra;
&ra = x;
Please help me if both of these code snippets are correct. If not, what errors do you see in them?
Your both expressions are incorrect, It should be:
int x, *ra;
ra = &x; // pointer variable assigning address of x
& is ampersand is an address of operator (in unary syntax), using & you can assign address of variable x into pointer variable ra.
Moreover, as your question title suggests: Assigning int value to an address.
ra is a pointer contains address of variable x so you can assign a new value to x via ra
*ra = 20;
Here * before pointer variable (in unary syntax) is deference operator gives value at the address.
Because you have also tagged question to c++ so I think you are confuse with reference variable declaration, that is:
int x = 10;
int &ra = x; // reference at time of declaration
Accordingly in case of the reference variable, if you want to assign a new value to x it is very simply in syntax as we do with value variable:
ra = 20;
(notice even ra is reference variable we assign to x without & or * still change reflects, this is the benefit of reference variable: simple to use capable as pointers!)
Remember reference binding given at the time of declaration and it can't change where pointer variable can point to the new variable later in the program.
In C we only have pointer and value variables, whereas in C++ we have a pointer, reference and value variables. In my linked answer I tried to explain differences between pointer and reference variable.
Both are incorrect.
When you declare a pointer, you assign it the address of a variable. You are attempting the other way round. The correct way would be:
int x,*ra;
ra = &x;
Both of those causes, in the way you have them in your question, undefined behavior.
For the first, you don't initialize the pointer, meaning it points to a random location (or NULL if the variable is global).
For the second, you try to change the address the variable is located at, which (if it even would compile) is not allowed.
Here's some annotated code:
int main () {
// declare an int variable
int x = 0;
// declare a pointer to an int variable
int *p;
// get the memory address of `x`
// using the address-of operator
&x;
// let `p` point to `x` by assigning the address of `x` to `p`
p = &x;
// assign `x` a value directly
x = 42;
// assign `x` a value indirectly via `p`
// using the dereference operator
*p = 0;
// get the value of `x` directly
x;
// get the value of `x` indirectly via `p`
// using the dereference operator
*p;
}
Note that dereferencing a pointer that doesn't point to a valid object of the specified type is not allowed.
So you normally shouldn't do things like the following (unless you really know what you are doing):
*(int*)(12345) = 42; // assign an integer value to an arbitrary memory address
Here is my 2 cent.
If you are going onto understanding pointer in C. First make the distinction between * the operator and * the type qualifier/specifier.
See that in C * is a syntaxique element that can plays both role but never at the same time. A type qualifier:
int a;
int * c = &a;
int * my_function_returning_pointer();
And for getting the proper int. As an operator. ( *c is an alias of a)
*c = 9;
I admit that is quite confusing and can trap a lot of beginner. Make sure that you recognize when * is used as an operator or when it is used as a type qualifier.
The same things apply to & although it is less often used as type qualifier.
int & f = returning_a_reference();
int my_function( int & refParam);
It is more often use for getting the address of an object. Thus it is used as an operator.
c = &f;
case 1:
int x,*ra;
&ra = x;
it is wrong in c, because in c we can point to a memory location by using a pointer ( i.e *ra in your case ). this can be done as fallows
int x, *ra; x ---------
ra=&x; ra --->1000 | value |
----------
NOTE : with out initializing a variable we can't use pointer to hold the address of that variable, so you better to first initialize variable, then set pointer to that memory location.
int x, *ra;
x=7;
ra=&x;
Fallowing may be helpful to you:
problems(mistake we do ) in handling pointers :
1.)
int a ,*p;
p=a; // assigning value instead of address. that leads to segmentation fault at run time.
2)
int a, *p;
&p=a; // look at here wrong assignment
3)
char *p="srinivas"
strcat(p, "helo" ) ; // we cant add a substring to the constant string.
4) int a=5, *p;
p=5; // the pointer here will points to location 5 in the memory, that may damage whole system, be care full in these type of assignments.

Variable addressing

int main()
{
int a = 10;
int *p; // int *p = a; gives me an error: invalid conversion from int to int *.
// Tell me why?
*p = a; // while this runs
cout << &a <<" "<<p;
}
Secondly &a and p gives 2 different values. According to me Address of a and the value stored in pointer p should be the same?
int *p = a, interpreted literally, takes the value stored in a and tries to interpret it as a memory address to store in p. While computationally legal, C++ won't allow this without an explicit typecast, because this is normally not what you want to do.
The reason why the statement int *p = a is different from *p = a is simple: the first statement, shorthand for the following
int *p;
p = a;
is initializing the pointer, so it expects a memory address on the RHS, while the second statement is assigning a value to the location pointed to by p, so expects (in this case) an integer on the RHS.
If you want to initialize p to point to a, you can use int * p = &a or p = &a instead, where & is the address-of operator. NEVER try to dereference uninitialized pointers! You will end up touching memory in an essentially arbitrary location, which could cause a segmentation fault (resulting in crash) or start overwriting other data in your program (resulting in obscure and non-reproducible bugs).
When you run your example code, p and &a have different values precisely because p was never assigned to point to the address of a. Some short background on why you might get any nonzero value in p at all: local variables are assigned from a special region of memory known as the stack, which also stores information about function calls and return addresses. Each process has their own stack. Crucially, though, unused regions of the stack aren't really zeroed out or otherwise cleaned up before use (except maybe in debug builds, which tend to assign really obvious values like 0xCCCCCCCC or 0xBAADF00D to uninitialized pointers). If your compiler doesn't automatically set default values for you (and release builds generally won't have such automatic initialization, for efficiency's sake), what you are seeing in p is what happened to be located in the memory assigned to p before your program set up its stack frame.
int *p = a; initializes a pointer p with a which isn't a pointer (hence the error), while *p=a; assigns a to the memory pointed to by p, syntactically speaking. Also, the former is an initialization, while the latter is assignment.
Note that in your case, *p=a invokes undefined behavior, as p doesn't point to program's legal memory, i.e you have not allocated memory for p.
You store a at the address that p points to (*p). If you want to store the address of a (&a) in p, you must use
p = &a;
Using int *p = a, gives an error, because p is a int*, while a is an int. Think of it as int* p = a.
int *p = a; - This means you are declaring a variable and assinging values to it. Variable name is p and its type is int * value you are assiging is a (10) which will be assigned to p. int *p = a; is equivalent to
int *p;
p = a;
We cant assing a int value to int *.
*p = a; - This you are assing int to the *p not p. so this is fine. Before doing this dont forget to allocate memory for p other it may leads to crash(undefined behaviour) because p might have some garbage values.
I hope you are trying to assing address of a to p. In that you case you can do like below.
int a;
int *p = &a;