Here is some code I wrote (using GCC's __restrict__ extension to C++):
#include <iostream>
using namespace std;
int main(void) {
int i = 7;
int *__restrict__ a = &i;
*a = 5;
int *b = &i, *c = &i;
*b = 8;
*c = 9;
cout << **&a << endl; // *a - which prints 9 in this case
return 0;
}
Or, the C version (in case the C++ version is not clear due to the use of an extension which every popular C++ compiler supports), using GCC:
#include <stdio.h>
int main(void) {
int i = 7;
int *restrict a = &i;
*a = 5;
int *b = &i, *c = &i;
*b = 8;
*c = 9;
printf("%d \n", **&a); // *a - which prints 9 in this case
return 0;
}
From what I've read, if I do *a = 5, it changes the value of the memory he, a, is pointing to; after that, the memory to which he is pointing to should not be modified by anyone else except a, which means that these programs are wrong because b and c modify it after that.
Or, even if b modifies i first, after that only a should have access to that memory (i).
Am I getting it correctly?
P.S: Restrict in this program doesn't change anything. With or without restrict, the compiler will produce the same assembly code. I wrote this program just to clarify things, it is not a good example of restrict usage. A good example of restrict usage you can see here: http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html
No.
Statements
*b = 8;
*c = 9;
will cause undefined behavior.
From documentation:
A pointer is the address of a location in memory. More than one pointer can access the same chunk of memory and modify it during the course of a program. The restrict type qualifier is an indication to the compiler that, if the memory addressed by the restrict-qualified pointer is modified, no other pointer will access that same memory. The compiler may choose to optimize code involving restrict-qualified pointers in a way that might otherwise result in incorrect behavior. It is the responsibility of the programmer to ensure that restrict-qualified pointers are used as they were intended to be used. Otherwise, undefined behavior may result.
Related
I created a function to change the value of *a, but it remains unchanged after the function fun has been executed.
Here's my code.
#include<iostream>
using namespace std;
void fun(int *b){
int *c = new int;
*c = 4;
b = c;
}
int main(){
int *a = new int;
*a = 2;
fun(a);
cout << *a << endl; // the output is 2 but I want it be 4
return 0;
}
I want *a be 4 in function fun
There's two ways, first the C++ way is to have a mutable (non-const) reference:
void fun(int& b) {
b = 4;
}
// Calling
int x = 0;
fun(x);
Then the classic C way is to use a regular pointer:
void fun(int* b) {
*b = 4;
}
// Calling
int x = 0;
fun(&x);
The reference approach is better because there's less syntax chaff both in calling the function, and in the function's implementation. There's also no risk you might get nullptr, a reference will be defined.
Note: Your use of new here has unintended consequences, like leaking memory. When you allocate with new you are responsible for releasing that memory.
b = c;
b is pointer, this operation makes b points to the address c represents. you do not change the value located on the address of 'a'
*b = *c;
This is the right
In your function instead of b=c you should write
*b = *c to change the value stored at the address pointed by b.
That is the reason your function does not work as desired.
In case of any query please feel free to clarify.
After encountering some cast and const issues, I have simplified my problem in a very small code snippet:
#include <iostream>
using namespace std;
int main()
{
const int a = 2;
const int* p = &a;
int* p_bis = (int*)p;
*p_bis = 42;
printf("\na = %d", a);
printf("\n&a = %p\n", &a);
printf("\np = %p", p);
printf("\n*p = %d\n", *p);
printf("\np_bis = %p", p_bis);
printf("\n*p_bis= %d", *p_bis);
}
After compiling this in C++17, it gives me the following output:
a = 2
&a = 0x7ffe9924d19c
p = 0x7ffe9924d19c
*p = 42
p_bis = 0x7ffe9924d19c
*p_bis= 42
I know that the line int* p_bis = (int*)p; is very dirty, because I do a C cast instead of a clean C++ cast, and furthermore I remove the constness with my cast. But What I don't understand however is how is it possible to have 2 values at the same address 0x7ffe9924d19c. Is it just some undefined behavior, and there is nothing else to understand?
While it is perfectly valid to cast a const pointer to a non-const one, and it also is valid to modify data through that pointer if the data was not originally defined as const, it is invalid to do so if the data was originally defined as const (which is your case). Changing the value of a variable that was defined as const (even through indirection) is undefined behavior.
The above applies to any version of both C and C++.
Is the following standards compliant c++ code?
int *p;
p = new int;
int &n = *p;
n = 5;
Furthermore, am I right in thinking that this code would essentially allocate memory for an int, then give a name, specifically n, to that memory location that could be used like a normal int type variable?
The given code
int *p;
p = new int;
int &n = *p;
n = 5;
is valid.
I'd write just “yep” as an answer but SO rules – and the sometimes very rule-based users – won't admit such a brief answer.
(I want to deal with "void" I am avoid "template class" because it is too much trouble)
ok establish some ground
int aa=3;
int bb=4;
int cc=0;
int *a, *b, *c;
a = &aa;
b = &bb;
c = &cc;
*c = *a +*b; //yields 7
but I want to do the following:
void *va;
void *vb;
void *vc;
va = a;
vb = b;
*c = (int)(*va + *vb); // <-- 3 errors see below
but I get errors:
error C2100: illegal indirection
error C2100: illegal indirection
error C2110: cannot add two pointers
You can't dereference void pointer.
If you want to turn them into int* you should do that before dereferencing;
(*(int*)vc) = (*(int*)va) + (*(int*)vb);
But you better be more specific, what exactly you want to do that you call "the following".
You cannot do many operations at all on truly unknown types in C or C++.
You could use Boost Variant to support multiple arithmetic types in one variable, or you could use a union and basically do what Boost Variant does by discriminating it yourself. Or you could build a type hierarchy and have virtual methods to perform the operations you need. But you can't perform arithmetic on values whose types have been completely erased.
The void pointer is a special pointer, it specifically denotes the absence of a type. These are often used to provide storage to a caller who does know the type and can cast back and forth.
Dereferencing a void* makes no sense and is, in-fact, invalid syntax, the whole point of dereferencing a pointer is to get the item being pointed to, if you don't specify what you're pointing at, you cant get it.
To "fix" your code you'd need to cast before dereferencing: http://www.ideone.com/eKxxn
#include <iostream>
int main() {
int ia = 1, ib = 2, ic = -1;
int *a = &ia, *b = &ib, *c = ⁣
void *va, *vb;
va = a;
vb = b;
*c = (int)(*static_cast<int*>(va) + *static_cast<int*>(vb));
std::cout << *c; // Outputs "3"
}
Can assign a pointer to a value on declaration? Something like this:
int * p = &(1000)
Yes, you can initialize pointers to a value on declaration, however you can't do:
int *p = &(1000);
& is the address of operator and you can't apply that to a constant (although if you could, that would be interesting). Try using another variable:
int foo = 1000;
int *p = &foo;
or type-casting:
int *p = (int *)(1000); // or reinterpret_cast<>/static_cast<>/etc
What about:
// Creates a pointer p to an integer initialized with value 1000.
int * p = new int(1000);
Tested and works. ;-)
There are two things not clear in the question to me. Do you want to set the pointer to a specific value (i.e address), or do you want to make the pointer point to some specific variable?
In the latter case, you can just use the address-of operator. The value of the pointer is then set to the address of some_int_variable.
int *p = &some_int_variable;
*p = 10; // same as some_int_variable = 10;
Note: What follows is evil changing of the pointer's value manually. If you don't know whether you want to do that, you don't want to do it.
In the former case (i.e setting to some specific, given address), you can't just do
int *p = 1000;
Since the compiler won't take the int and interpret it as an address. You will have to tell the compiler it should do that explicitly:
int *p = reinterpret_cast<int*>(1000);
Now, the pointer will reference some integer (hopefully) at address 1000. Note that the result is implementation defined. But nevertheless, that are the semantics and that is the way you tell the compiler about it.
Update: The committee fixed the weird behavior of reinterpret_cast<T*>(0) that was suggested by a note and for which i provided a workaround before. See here.
Um. I don't think you can take a non-const address of a constant like that.
but this works:
int x = 3;
int *px = &x;
cout << *px; // prints 3
or this:
const int x = 3;
const int *px = &x;
const int *pfoo = reinterpret_cast<const int*>(47);