Why this program only works when I initialize a and b.
I want to pass it without initializing a and b, for example:
numChange(10,15);
Is this possible ?
#include <iostream>
using namespace std;
void numChange(int *x,int *y)
{
*x = 99;
*y = 77;
}
int main()
{
numChange(10,15);
//int a=10;
//int b=15;
//numChange(&a,&b);
cout<<a<<" , "<<b<<endl;
return 0;
}
Because you have defined your function to receive pointers, but when you call that function you are trying to pass an int.
The compiler is expecting memory addresses and you are trying to pass constants.
It does not make sense, you are trying to do something like 10 = 99; 15 = 77;?
numChange(10,15);
//int a=10;
//int b=15;
It seems that you are hopping that a = 10 = 99 and b = 15 = 77;
If this was possible, it means that I could never (after the call of numChange(10,15);) make a variable to actually have the value 10 because 10 is "pointing" to 99 (is not).
Recall: a pointer is an integer containing a location in memory.
This:
int a, b;
...
a = b;
copies the integer stored at the memory location reserved for 'b' to
the memory location reserved for 'a'.
This:
int *a, b;
...
a = &b;
stores the location of 'b' in 'a'. Following it with this:
*a = 42;
will store 42 in the memory location stored in 'a', which is the
variable 'b'.
Now, let's look at your code. This:
void numChange(int *x,int *y)
tells the compiler that 'numChange' will be called with two
pointers--that is, memory addresses. This part:
*x = 99;
*y = 77;
then stores two integers at the locations given in 'x' and 'y'.
When you call:
numChange(10,15);
the arguments are integers instead of memory location. However under
the hood, memory locations are also integers so the compiler converts
the arguments to pointers. Effectively, it's doing this:
numChange((int *)10, (int*)15);
(It should issue a warning when this happens, since it's almost never
a good idea, but it will do it.)
Basically, your call to 'numChange' tells it that there are integer
variables at memory addresses 10 and 15, and 'numChange' carries on
and stores integers at those memory locations. Since there aren't
variables (that we know of) at those locations, this code actually
overwrites some other data somewhere.
Meanwhile, this code:
int a=10;
int b=15;
numChange(&a,&b);
creates two integer variables and then passes their addresses in
memory to 'numChange'. BTW, you don't actually need to initialize
them. This works too:
int a, b;
numChange(&a,&b);
What's important is that the variables are created (and the compiler
sets aside RAM for them) and that their locations are then passed to
'numChange'.
(One aside: I'm treating variables as always being stored in RAM.
It's safe to think of them this way but modern compilers will try to
store them in CPU registers as much as possible for performance
reasons, copying them back into RAM when needed.)
Related
i am learning c++ and i find this bit confusing about the pointers . is it allowed or is it possible to modify the variable int a using pointer variable ?
here's the code :
#include <iostream>
int main(){
int a ; // int variable
int *p ; // pointer
a = 10 ;
*p =15 ;
std:: cout << a ;
return 0;
};
does *p = 15 change the value of a ?
i got error when i tried to run the code :
zsh: bus error
There's no relationship between p and a. p points to invalid memory, and dereferencing or assigning to it is undefined behavior.
If you want modifications to p to affect a, you need to set where it points to.
int a;
int *p = &a;
Silvio's answer is correct.
Bus errors occur when your processor cannot even attempt the memory access requested.
This usually happens when using a processor instruction with an address that does not satisfy its alignment requirements.
you can read more about this here.
You need to assign the address of variable a to the pointer p.
p = &a;
Now, if you will change the value of the pointer to 15 it will be reflected in the variable a. And you won't get an error.
This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 7 years ago.
I have a few questions. This isn't homework. I just want to understand better.
So if I have
int * b = &k;
Then k must be an integer, and b is a pointer to k's position in memory, correct?
What is the underlying "data type" of b? When I output it, it returns things like 0x22fe4c, which I assume is hexadecimal for memory position 2293324, correct?
Where exactly is memory position '2293324'? The "heap"? How can I output the values at, for example, memory positions 0, 1, 2, etc?
If I output *b, this is the same as outputting k directly, because * somehow means the value pointed to by b. But this seems different than the declaration of b, which was declared int * b = k, so if * means "value of" then doesn't mean this "declare b to the value of k? I know it doesn't but I still want to understand exactly what this means language wise.
If I output &b, this is actually returning the address of the pointer itself, and has nothing to do with k, correct?
I can also do int & a = k; which seems to be the same as doing int a = k;. Is it generally not necessary to use & in this way?
1- Yes.
2- There's no "underlying data type". It's a pointer to int. That's its nature. It's as data type as "int" or "char" for c/c++.
3- You shouldn't even try output values of memory which wasn't allocated by you. That's a segmentation fault. You can try by doing b-- (Which makes "b" point to the "int" before it actual position. At least, to what your program thinks it's an int.)
4- * with pointers is an operator. With any data type, it's another data type. It's like the = symbol. It has one meaning when you put == and another when you put =. The symbol doesn't necesarilly correlates with it meaning.
5- &b is the direction of b. It is related to k while b points to k. For example, if you do (**(&b)) you are making the value pointed by the value pointed by the direction of b. Which is k. If you didn't changed it, of course.
6- int & a = k means set the direction of a to the direction of k. a will be, for all means, k. If you do a=1, k will be 1. They will be both references to the same thing.
Open to corrections, of course. That's how I understand it.
In answer to your questions:
Yes, b is a pointer to k: It contains the address of k in the heap, but not the value of k itself.
The "data type" of b is an int: Essentially, this tells us that the address to which b points is the address of an int, but this has nothing to do with b itself: b is just an address to a variable.
Don't try to manually allocate memory to a specific address: Memory is allocated based of the size of the object once initialized, so memory addresses are spaced to leave room for objects to be allocated next to each other in the memory, thus manually changing this is a bad idea.
* In this case is a de-reference to b. As I've said, b is a memory address, but *b is what's at b's address. In this case, it's k, so manipulating *b is the same as manipulating k.
Correct, &b is the address of the pointer, which is distinct from both k and b itself.
Using int & a = k is creating a reference to k, which may be used as if it were k itself. This case is trivial, however, references are ideal for functions which need to alter the value of a variable which lies outside the scope of the function itself.
For instance:
void addThree(int& a) {
a += 3;
}
int main() {
int a = 3; //'a' has a value of 3
addThree(a); //adds three to 'a'
a += 2; //'a' now has a value of 8
return 0;
}
In the above case, addThree takes a reference to a, meaning that the value of int a in main() is manipulated directly by the function.
This would also work with a pointer:
void addThree(int* a) { //Takes a pointer to an integer
*a += 3; //Adds 3 to the int found at the pointer's address
}
int main() {
int a = 3; //'a' has a value of 3
addThree(&a); //Passes the address of 'a' to the addThree function
a += 2; //'a' now has a value of 8
return 0;
}
But not with a copy-constructed argument:
void addThree(int a) {
a += 3; //A new variable 'a' now a has value of 6.
}
int main() {
int a = 3; //'a' has a value of 3
addThree(a); //'a' still has a value of 3: The function won't change it
a += 2; //a now has a value of 5
return 0;
}
There are compliments of each other. * either declares a pointer or dereferences it. & either declares a (lvalue) reference or takes the address of an object or builtin type. So in many cases they work in tandem. To make a pointer of an object you need its address. To use a pointer as a value you dereference it.
3 - If k is a local variable, it's on the stack. If k is a static variable, it's in the data section of the program. The same applies to any variable, including b. A pointer would point to some location in the heap if new, malloc(), calloc(), ... , is used. A pointer would point to the stack if alloca() (or _alloca()) is used (alloca() is similar to using a local variable length array).
Example involving an array:
int array_of_5_integers[5];
int *ptr_to_int;
int (*ptr_to_array_of_5_integers)[5];
ptr_to_int = array_of_5_integers;
ptr_to_array_of_5_integers = &array_of_5_integers;
Could anyone please elaborate the behaviour of reference in this code and why is it printing 12 in first line instead of 11.
Below is the code
http://ideone.com/l9qaBp
#include <cstdio>
using namespace std;
int &fun()
{
static int x = 10;
x++;
return x;
}
int main()
{
int *ptr=&fun();
int *ptr1=&fun();
printf("%p %p \t %d %d",(void*)ptr,(void*)ptr1,*ptr,*ptr1);
return 0;
}
the output of the code is
134519132 134519132 12 12
Please explain why 12 is getting printed on first call not 11 i understand when second call is made it should print 12
ptr and ptr1 are pointing to the same variable static int x. The second call changed the value of static int x to 12, then you print out the value by derefernce ptr and ptr1, the same result will be printed out.
The int reference returned by fun() is the same for both calls (ref to the static x), hence the address of that reference is the same for both calls. Hence the resulting dereference of that identical address is the current identical value.
Your error seems to be in thinking that printf() prints *ptr as soon as it comes available. It does not; printf() is not called until both ptr and ptr1 are computed. Since both ptr and ptr1 point to the same memory location, which is a static variable, and that location is updated after both the first call to fun() and the second, the address holds that value.
static variables have lifetime extent and are stored in statically allocated memory. It means that the storage of static local variables inside a function is not allocated and deallocated on call-stack.
Once x is initialized at compile time, the value of x is kept stored between the invocations of function fun.
As C++ statements are executed sequentially, printf will be executed after the invocations of two function calls in the given lines
int *ptr=&fun();
int *ptr1=&fun();
and therefore the value of x will be 12 before the execution of printf statements.
Keep in mind that
int *ptr=&fun();
int *ptr1=&fun();
is not equivalent to
int& (*ptr)() = &fun;
int& (*ptr1)() = &fun;
In second snippet ptr and ptr1 both holding the address of function fun. In this case you need to call function directly or by using these pointers as
int a = ptr();
int b = ptr1();
after this invocation value of a and b will be 12.
I'm a programming and c++ novice. I'd appreciate some help with this.
the following program (in c++) doesn't encounter any problem either in compilation or run-time:
int main()
{
int b = 5;
int*a = &b;
*(a+5) = 6;
return 0;
}
But according to everything I learned it shouldn't work, because a is a pointer to a single variable. What am I missing here?
Your program should indeed not encounter any problem at compile time. It is all valid code with regards to compilation.
However it will encounter undefined behaviour at runtime as a+5 is not a valid address.
If you want to know why it should compile, you can write code like this:
int func( int * buf, size_t size )
{
for( size_t i = 0; i < size; ++i )
{
*(buf + size) = static_cast<int>(i); // or (int)i in C
}
}
int main()
{
int buf[ 6 ];
func( buf, 6 );
}
In your code a is a pointer to memory. a + 5 means an address 5 "ints" on from where a points. As a was pointed at a single integer b, there are no guarantees about such an address. Interestingly enough, it is well defined to refer to a+1 even though it points to a place in memory that you should not read from or write to. But the pointer itself has some guarantees, i.e. it will be greater than a and if you subtract 1 from it you will get back to a and if you do a ptrdiff between it and a you will get 1. But that is just a special property of "one past the end" which allows programmers to specify memory ranges.
The program do have an undefined behaviour:
int main()
{
//This cause the loading of the "main" function to allocate memory for variable b
//It could be in a memory page that was already allocated to the program
//or in a new allocated page.
int b = 5;
//Here a just getting the address of variable b.
int*a = &b;
//This is the undefined behavior and can end up in two cases:
// 1. If (a+5) value is in a memory space that is allocated to the application.
// Then no runtime error will happen, and the value will be writing there.
// probably dirting some other value, and can cause an undefined behavior later
// in the application execution.
// 2. If (a+5) value is in a memory space that wasn't allocated to the application.
// the application will crash
*(a+5) = 6;
return 0;
}
Now, since a page size is probably 4096 and b is somewhere within a page, *b+5 is in most cases still be in the same page. If you want to challenge it more change it from 5 to 5000 or higher and the chance for crashes will increase.
Yes it shouldn't work when you access memory space which is not in your process region, but perhaps no one has owned that particular region ((a + 5)) which didn't cause run time illegal memory access or it can. Hence its a UB.
Just adding to the existing answers.
The access
*(a+5) = a[5]
So this is the location not allocated by you.
In the case of array say
int a[6];
You have a valid access from a[0] to a[5] where a[5] is the last element of the array and any further access like a[6] will lead to undefined behavior as that location is not allocated by you.
Similarly you just have a integer allocated like
int b=5;
int *a = &b;
a is a pointer pointing to &b i.e address of b.
So the valid access for this is just a[0] which is the only location allocated by you on the stack.
Any other access like a[1] a[2]... and so on will lead to undefined behavior.
The access turns out to be VALID if you have something like
int b[6];
int *a = b;
Now a[5] will give the value of the last element of the array b
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <iostream>
using namespace std;
char a[21]; // If this is put inside the function unter -> junk output
char* b="";
void unter()
{
char *new_str = "";
strcpy(a, new_str);
char str_temp[10]="";
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
sprintf(str_temp,"%d",chnum);
b = strcat(a, str_temp);
b = strcat(b, "_from");
sprintf(str_temp,"%d",mynode);
b = strcat(b, str_temp);
b = strcat(b, "to");
sprintf(str_temp,"%d",neighbor1);
b = strcat(b, str_temp);
}
int main()
{
unter();
cout << a;
cout << b;
std::cin.get();
}
This is my code in C++. I'm not sure how the character array 'a' also has the same values as 'b'. And moreover, when I declare 'a'
char a[21];
inside function unter(), I'm getting some junk value for 'b'(as output). Care to explain how?
a is a char array and b is a pointer that points to a, so when printing them, they always print the same thing. When you move the declaration for a into unter, it is destroyed when unter returns, leaving b a dnagling pointer, so you get garbage when you print it.
b = strcat(a, str_temp);
is probably what's causing your issue, since the return value from strcat() is the first parameter that was passed to it, hence why you're seeing a and b becoming equal, since b is getting set to a in that call.
strcat() returns the result of the concatenation operation, so
b = strcat(a, str_temp);
results in b pointing to the array a[]. The subsequent strcat() operations effectively do the same, so the end result is that b points to a[] as you observe. If you declare a[] inside unter() it will have local scope to that function, with the result that the global variable b will point to random/undefined memory contents after you exit the call to unter().
It's mildly worth noting that you're doing a lot of work that could be accomplished more easily with
sprintf(a, "%d_from%dto%d", chnum, mynode, neighbor1);
You can do the whole concatenation and sprintf's in a single line.
char* b="";
void unter()
{
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
char str_temp[21];
sprintf(str_temp,"%d_from%dto%d", chnum, mynode, neighbor1);
b = new char[strlen(str_temp)+1];
b = strcpy(b, str_temp);
}
Only funny thing is you must remember to delete b when you are done. The other option is using the a buffer and sprintf directly to it:
char a[21];
void unter()
{
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
char str_temp[21];
sprintf(a,"%d_from%dto%d", chnum, mynode, neighbor1);
}
When you define a inside the function, memory for the variable a is allocated on stack. This memory is destroyed when the function exits. Your pointer b is pointing to starting address of a. Now, if you try to access b outside the function, it is pointing to a memory location which is already destructed and contain garbage values. Basically, b becomes a dangling pointer.
If you declare a inside the unter() function, then it is only scoped inside that function. Attempt to print b from outside the function will print junk since it is pointing to a which is already destroyed.
This is a classic example of why you should always make sure to not to point to a local variable from a global one.
In addition to the other hints provided, you should take notice of the line
b = strcat(b, str_temp);
which seems rather inappropriate for b is merely defined as a char pointer to a single byte storage ("" defines an empty string, i.e. an array of chars with a single element containing '\0')
So when strcat appends to b, it creates a buffer overrun.
Edit:Actually I just noticed that b was assigned to point to a, (thanks to the line preceding the one mentionned) so that would then be ok, since a may have the room for this... It doesn't make sense however, to need the two variables.
Maybe what you do not understand, is that although strcat() returns a pointer, this return doesn't need to be "consumed", it is merely a convenience, for when we chain commands an such. In other words you can simply write:
strcat(a, str_temp);
Not requiring any char * b.