char a[] = "hello";
My understanding is that a acts like a constant pointer to a string. I know writing a++ won't work, but why?
No, it's not OK to increment an array. Although arrays are freely convertible to pointers, they are not pointers. Therefore, writing a++ will trigger an error.
However, writing
char *p = a;
p++;
is fine, becuase p is a pointer, with value equal to the location of a's initial element.
a++ is not well-formed since a decays to a pointer, and the result of the decay is not an lvalue (so there is no persistent object whose state could be "incremented").
If you want to manipulate pointers to the array, you should first create such a pointer:
char* p = a; // decayed pointer initializes p
a++; // OK
++a; // even OKer
This is a very good question actually. Before discussing this, let's back to the basic concepts.
What happens when we declare a variable ?
int a=10;
Well, we get a memory location to store the variable a. Apart from this an entry is created into Symbol table that contains the address of the variable and the name of the memory location (a in this case).
Once the entry is created, you can never change anything into the symbol table, means you can't update the address. Getting an address for a variable is not in our hand, it's done by our computer system.
Let's say, we get address 400 for our variable a.
Now computer has assigned an address for the variable a, so at a later point, we can't ask computer to change this address 400 because again, it's not in our hand, our computer system does it.
Now you have an idea about what happens when we declare a variable.let's come to our question.
Let's declare an array.
int arr[10]
So, when we declare this array, we create the entry into the symbol table and, store the address and the name of the array into the symbol table.
let's assume we get address 500 for this variable.
Let's see what happens when we want to do something like this :
arr++
when we increment arr, we want to increment 500, that is not possible and not in our hand, because it has been decided by the computer system, so we can't change it.
instead of doing this we can declare a pointer variable
int * p= &arr;
What happens in this situation is: again an entry is created into the symbol table that stores the name and the address of the pointer variable p.
So when we try to increment p by doing p++, we are not changing the value into the symbol table, instead we are changing the value of the address of the pointer variable, that we can do and we are allowed to do.
Also it's very obvious that if we will increment the a the ultimately we are going to loss the address of our array. if we loss the address of array then how will we access the array at a later point ?
It is never legal in C to assign to an expression of array type. Increment (++) involves assignment, and is thus also not legal.
What you showed at the top is a special syntax for initializing a char array variable.
I think this answer here explains "why" it's not a good idea;
It's because array is treated as a constant pointer in the function it is declared.
There is a reason for it. Array variable is supposed to point to the first element of the array or first memory instance of the block of the contiguous memory locations in which it is stored. So, if we will have the liberty to to change(increment or decrement ) the array pointer, it won't point to the first memory location of the block. Thus it will loose it's purpose.
Related
so in the picture, it says that the problem is with the starting address of the array as we cant change it. but why does this apply only for arrays. int x = 1; we could easily say int y = x; and it would work. doesnt this change the memory address of the variable too?
[tl;dr] The first and sole reason why newValues = oldValues; is illegal ("will not work") is that the C++ standard prohibits it. Array assignment is not defined, supported or allowed in C++, and therefore any such statement is invalid code. Any other attempts to "explain" it, using memory addresses or other speculations, only obfuscates the simple truth that it is the definition of the language that decides what is legal and what is not in that language.
The following are quoted from the posted "textbook" excerpt, which I find to be both wrong and misguided for what looks to be an introduction to C++ basics.
the name of an array without the brackets and subscript stands for the array's starting memory address
Wrong. The name stands for the variable that it denotes, which has array type. While it is true that an array can decay to a pointer ("starting memory address) in certain contexts, it is certainly not true that an array name is the same with its starting address. For example, both sizeof oldValues and typeid(oldValues) are valid expressions, which would mean something very different if replacing oldValues with its memory address.
the statement will not work because you cannot change the starting memory address of an array
The statement "will not work" is correct, but the given reason is still wrong. No assignment changes the address of its left-hand side, it only changes its value. Array assignment does not work because the language does not define it, and for no other reason. Consider for example the following.
int a[4], b[4];
a = b; // error, array assignment not allowed
struct { int n[4]; } c, d;
c = d; // ok, using default copy assignment
What exactly does this do?
int test = *(int*)(0x154512);
0x154512
is an integer, written in base 16.
(int*)(0x154512)
says to treat that number as the address of an int variable.
*(int*)(0x154512)
says to dereference that address, or get the int value at that address.
int test = *(int*)(0x154512)
says to declare the int variable test and assign it the int value located at address 0x154512.
Let's break this down into pieces.
0x154512 is a hex value, or base-16, which is often used for memory addresses for convenience reasons.
int* declares a pointer to a value of type int. So, (int*)(0x154512) means 0x154512 is being treated as a memory address, which we expect to hold an integer.
The last * on the left is the dereference operator, which means "get the value located at this pointer" more or less.
So it copies the integer at memory address 0x154512 to the variable "test".
For more information on pointers:
http://www.cplusplus.com/doc/tutorial/pointers/
If you're planning to do a lot of C++ in the future, make sure to give this a nice, long read. Pointers are fun.
One line get integer value stored at 0x154512 memory location
When implementing a two dimensional array like this:
int a[3][3];
these hold: A=&A[0], at the same time A[0]=&A[0][0]. So, A=&(&A[0][0]), what basically says that A is the address of the address of the first element of the array, which is not quite true. What is my mistake here? Does A really decay to a pointer to a pointer?
Your mistake is that you have an incorrect understanding of the relationship between arrays and pointers. An array is not a pointer. It is an array. However, an array is implicitly convertible to a pointer to its own first element. So, while this expression does evaluate to true:
A == &A[0]
It is not correct to say that A is &A[0]. The conversion does not happen in all expressions. For example:
&A
This does not take the address of the address of the first element of A (that doesn't even make sense). It takes the actual address of A, who's type is int[3][3]. So the type of &A is int(*)[3][3], read as "pointer to array of 3 arrays of 3 ints".
The primary difference between &A and &A[0] is that if you add 1 to &A, you will get an address that is 3 * 3 * sizeof(int) bytes away, while if you add 1 to &A[0], you will get a pointer that is only 3 * sizeof(int) bytes away.
With all this in mind, you should be able to see where your mistake is. A[0] is not &A[0][0], but it is implicitly convertible to it. However, like all conversions, this results in a temporary, which you cannot take the address of. So the expression &(&A[0][0]) doesn't even make sense.
Because of reactions on my previous answer I did some research to learn more on whatever was wrong in my explanation.
Found a rather elaborate explanation of the topic here :
http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c
I'll try to summarize :
if you have following :
char array_place[100] = "don't panic";
char* ptr_place = "don't panic";
the way that this is represented in memory is entirely different.
whereas ptr_place is a real pointer, array_place is just a label.
char a = array_place[7];
char b = ptr_place[7];
The semantics of arrays in C dictate that the array name is the address of the first element of the array, which is not the same as saying that it is a pointer. Hence in the assignment to a, the 8th character of the array is taken by offsetting the value of array_place by 7, and moving the contents pointed to by the resulting address into the al register, and later into a.
The semantics of pointers are quite different. A pointer is just a regular variable that happens to hold the address of another variable inside. Therefore, to actually compute the offset of the 8th character of the string, the CPU will first copy the value of the pointer into a register and only then increment it. This takes another instruction [1].
This point is frequently ignored by programmers who don't actually hack on compilers. A variable in C is just a convenient, alphanumeric pseudonym of a memory location. Were we writing assembly code, we would just create a label in some memory location and then access this label instead of always hard-coding the memory value - and this is what the compiler does.
Well, actually the address is not hard-coded in an absolute way because of loading and relocation issues, but for the sake of this discussion we don't have to get into these details.
A label is something the compiler assigns at compile time. From here the great difference between arrays and pointers. This also explains why sizeof(array_place) gives the full size of the array where as the size of a pointer will give the size of a pointer.
I must say, I was not aware of these subtle differences myself, and I have been coding for quite a long time in C and C++ and with arrays too.
Nevertheless if the name of the array element is the address of the first element of the array. You can create a pointer and initialise it what that value
char* p = array_place
p will point to the memory location where the characters are.
to conclude :
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so p=array_place and p++ are legal. But an array name is not a variable; constructions like array_place=p and array_place++ are illegal. That I did know ;-)
I have the following program which defines 2 integers and a pointer to an integer.
#include <stdio.h>
int main() {
int bla=999;
int a=42;
int* pa=&a;
printf("%d \n", *pa);
printf("%d \n", pa);
pa++;
//*pa=666; //runs (no error), but the console is showing nothing at all
printf("%d \n", *pa);
printf("%d \n", pa);
pa++;
//*pa=666; //runs and changes the value of *pa to 666;
printf("%d \n", *pa);
printf("%d \n", pa);
}
The output is:
42
2686740
2686744
2686744 //this value is strange, I think
999
2686748
The adresses are making sense to me, but the fourth value is strange, because it is exactly the adress of the int. Can somebody explain that behaviour ?
When I comment *pa=666 (the first apperance) in, the console shows nothing, so here is some sort of error, but the compiler does not show an error. Maybe this is because of the size of int on my system, I have a 64bit-windows-os, so maybe the int is 64 bit and not 32 ? And because of that the *pa-value is 999 after the second increment and not the first ?
I am sure, there are a lot of C-programmers out there who can explain what is going on :)
int* pa=&a;
pa is pointer to an integer and accessing *pa is defined.
Once you increment your pointer, then the pointer is pointing to some memory(after p) which is not allocated by you or not known to you so dereferencing it leads to undefined beahvior.
pa++;
*pa is UB
Edit:
Use proper format specifier to print the pointer value %p as pointed out by #haccks
The output is not strange, it is to be expected: You have three variables in main(), all of which are stored on the stack, and which happen to be right one after the other. One of these variables is the pointer itself. So, when you dereference the pointer in the third line, you get the current value of the pointer itself.
Nevertheless, this output is not predictable, it is undefined behavior: You are only allowed to use pointer arithmetic to access data within a single memory object, and in your case, the memory object is just a single int. Consequently, accessing *pa after the first pa++ is illegal, and the program is allowed to do anything from that point on.
More specifically, there is no guarantee which other variables follow a certain variable, in which order they follow, or if there is accessable memory at all. Even reading *pa after the first pa++ is allowed to crash your program. As you have witnessed, you will not experience a crash in many cases (which would be easy to debug), yet the code is still deeply broken.
You are using wrong format specifier to print address. This will invoke undefined behavior and once the UB is invoked, all bets are off. Use %p instead.
printf("%p \n", (void *)pa);
Another problem is that after execution of pa++;, you are accessing unallocated memory and another reason for UB.
You're not smarter than your compiler.
As said by another answer what you do is Undefined Behaviour. With pa you are just doing non-sense, it does'nt correspond to any reasonlable algorithm for a defined goal: it's non sense.
However I will propose you a possible scenario of what's happenning. Though much of it could be false because compilers do optimizations.
int bla=999;
int a=42;
int* pa=&a;
These variables are allocated on the stack.
When writing pa = &a you say "I want pointer pa to be equal to the address of a".
Probably the compiler could have allocated the memory in the order or declaration, which would give something like:
bla would have address 0x00008880
a would have address 0x00008884
pa would have address 0x00008888
when you do pa++ you're telling: move my pointer of int to the next position of int in memory.
As ints are 32 bits, you're doing pa = pa + 4bytes i.e. pa = 0x00008888
Notice that, by chance !,you're probably pointing to the address of the pa pointer.
So now the pointer pa contains its own address... which is pretty esoteric and could be called ouroboros.
Then you're asking again pa++... so pa = pa + 4 bytes i.e. pa = 0x0000888c
So now you are probably accessing an unknown memory zone. It could be an access violation. It's undefined behaviour if you ever want to read or write.
When you first assigned the pointer it pointed to 2686740. The pointer is an integer pointer and integers use 4 bytes (usually, on your machine it used 4). That means pa++ is going to increase the value to be 4 more which is 2686744. Doing it again resulted in 2686748
If you were to look at the resulting assembly code the order of your local variables would be switched around. The ordering was a, pa, bla when the code ran. Because you don't have explicit control over this ordering the output of your printing is considered to be undefined
After the first time you did pa++ the pointer pointed at itself, that is why you got the "strange value"
As mentioned by many of the other answers, this is not good use of pointers and should be avoided. You don't have control over what the pointer is pointing to in this situation. A much better use of pointer arithmetic would be pointing at the beginning of an array and then doing pa++ to point to the next element in the array. The only problem you could experience then would be incrementing past the last element of the array
Are you trying to increment the value in a through the pointer *pa?
If so, do: (*pa)++. The brackets are crucial as they mean "take the value of the pointer", then use that address to increment whatever it is referencing.
This is completely different to *pa++ which simply returns the value pointed to by *pa and then increments the pointer (not the thing that it is referencing).
One of the little traps of C syntax. K&R has a few pages devoted to this, I suggest you try some of the examples there.
I'm having a hard time understanding pointers, particularly function pointers, and I was hoping someone could give me a rundown of exactly what they are and how they should be used in a program. Code blocks in C++ would be especially appreciated.
Thank you.
The concept of indirection is important to understand.
Here we are passing by value (note that a local copy is created and operated on, not the original version) via increment(x):
And here, by pointer (memory address) via increment(&x):
Note that references work similarly to pointers except that the syntax is similar to value copies (obj.member) and that pointers can point to 0 ("null" pointer) whereas references must be pointing to non-zero memory addresses.
Function pointers, on the other hand, let you dynamically change the behaviour of code at runtime by conveniently passing around and dealing withh functions in the same way you would pass around variables. Functors are often preferred (especially by the STL) since their syntax is cleaner and they let you associate local state with a function instance (read up about callbacks and closures, both are useful computer science concepts). For simple function pointers/callbacks, lambdas are often used (new in C++11) due to their compact and in-place syntax.
The pointer points to the point, is an integer value that has the address of that point.
Pointers can point to other pointers. Then you can get the values more-indirect way.
Reference operator (&):
You may equate a pointer to a reference of a variable or a pointer.
Dereference operator (*):
You may get the value of cell pointed by the pointer.
Arrays are decayed into a pointer when passed to a function by not a reference.
Function pointers are not inlined and makes program more functional. Callback is an example to this.
As an analogy, think of the memory in the computer as an Excel sheet. The equivalent of assigning a value to a variable in a C/C++ program would be to write something into a cell on the Excel sheet. Reading from a variable would be like looking at a cell's content.
Now, if you have a cell (say C3) whose content is "B8" you can interpret that content as a reference to another cell. If you treat the cell C3 in that manner, C3 becomes like a pointer. (In Excel, you can actually achieve this behavior by entering =B8 into C3).
In such a scenario, you basically state that the cell whose value you're interested in is referenced in C3. In C++, this could be something like:
int B8 = 42;
int* C3 = &B8;
You now have two variables that occuppy memory. Now, if you want to know what C3 points to, you'll use
int my_value = *C3;
As for function pointers: these are variables like ordinary pointers but the address (cell) they point to is not just a value but rather a function you can call.
Here you can find some example uses of Function pointer:
http://www.cprogramming.com/tutorial/function-pointers.html
In order to understand pointers one needs to understand a bit about hardware and memory layout.
Computer memory can be seen as a cupboard with drawers. A pointer can point to an arbitrary drawer, when you "dereference" the pointer you are looking inside the drawer, i.e. the value stored in the "drawer":
e.g. ten numbers stored after one another
short a[] = {9,2,3,4,5,6,7,8,1,-1] ;
in memory the values that consist the array 'a' are stored sequentially
+---+---+---+---+---+---+---+---+---+---+
a->| 9 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1 | -1|
+---+---+---+---+---+---+---+---+---+---+
the 'a' array above is a pointer and is the start address where the
values are stored in memory.
short* ptr = 0; // a pointer not pointing to anything (NULL)
ptr = a + 5; // the pointer is now pointing to the 6th value in the array
// the + 5 is an offset on the starting address of a and since the type of
// a is short int array the compiler calculates the correct byte offset based
// on that type. in the above example 5 is 5 short ints since ptr is of type
// short*
*ptr has the value 6 i.e. we are looking at what the ptr is pointing to.
The size of each "drawer" is determined of the data type that is stored
In the above example 10 short ints are stored, every short int occupies 2 bytes
so the whole array occupies 20 bytes of memory (sizeof(a))
Variables store values.
Pointers store values too. The only difference is that they are memory addresses. They are still numbers.
Nothing complicated here.
You could store all pointers in int or long variables:
int p = 43567854;
char *p1 = (char *) p;
But advantage of storing them in pointer variables is that you can describe what type of variable is saved at the address the pointer points to.
What gets complicated about pointers is the cryptic syntax you have to use with them. Syntax is cryptic so that it's short to type.
Like:
&p = return address of variable
*p = return the value of first member of array that is stored at the address
By using the two rules above we can write this cryptic code:
&(*++t)
Which translated into human language gets quite long:
Increase value of t by 1. this now points to second member of array of values pointer points to. then get value of second member (*) and then get address of this value. if we print this pointer it will print whole string except the first character.
You should make a "pointers syntax cheat sheet.txt" and you are good.
And have open "Pointers tests" projects to test everythng that is unclear to you.
Pointers are similar to regular expressions in a way.