fn main() {
let c: i32 = 5;
let rrc = &&c;
println!("{}", rrc); // 5
println!("{}", *rrc); // 5
println!("{}", **rrc); // 5
}
In C/C++ language, rrc likes a two level pointer. In this example, rrc doesn't mean this in rust. What do & and * mean in Rust?
The reason they all print the same thing is that borrows (&T) in Rust implements Display for T: Display by dispatching it to the pointed type. If you want to print the actual pointer value, you have to use {:p}.
let c = 5;
let rrc = &&c;
println!("{:p}", rrc); // 0x7ffc4e4c7590
println!("{:p}", *rrc); // 0x7ffc4e4c7584
println!("{}", **rrc); // 5
See the playground.
It is simply two reference operators. The reason why they all print 5 is because when printing a reference it automatically de-references it:
fn main() {
let c: i32 = 5;
let rrc = &c;
let rrc = &rrc; // this is &&c
}
Related
Running the following code gives a segmentation fault:
fn main() {
let val = 1;
let ptr = val as *const i32;
unsafe { println!("{:?}", *ptr) };
}
Output:
[1] 69212 segmentation fault (core dumped) cargo r
However, when val is put in as a reference & while declaring the raw pointer, the code runs as intended and as val is printed out.
fn main() {
let val = 1;
let ptr = &val as *const i32;
unsafe { println!("{:?}", *ptr) };
}
Output:
1
So what is the shared reference doing here and why does the program fail without it? Isn't a reference in rust also a pointer with extra schematics? Why to we need to create a pointer to a reference and not directly to the val itself?
This issue can be answered by looking at the different semantics of the both code lines you provided.
fn main() {
let val = 1;
println!("{:?}", val as *const i32); // Output: 0x1
println!("{:?}", &val as *const i32); // Output: 0x7ff7b36a4eec (probably little different)
}
Without the reference the value of the variable is take as it is to be used to dereference the memory. This leads of course to a segmentation fault, since it will be not in the allowed address range of the program.
Only when the reference operator is used, the address of the variable is casted to a raw pointer, which then later can be dereferenced without any segmentation fault.
I have a type:
struct Foo {
memberA: Bar,
memberB: Baz,
}
and a pointer which I know is a pointer to memberB in Foo:
p: *const Baz
What is the correct way to get a new pointer p: *const Foo which points to the original struct Foo?
My current implementation is the following, which I'm pretty sure invokes undefined behavior due to the dereference of (p as *const Foo) where p is not a pointer to a Foo:
let p2 = p as usize -
((&(*(p as *const Foo)).memberB as *const _ as usize) - (p as usize));
This is part of FFI - I can't easily restructure the code to avoid needing to perform this operation.
This is very similar to Get pointer to object from pointer to some member but for Rust, which as far as I know has no offsetof macro.
The dereference expression produces an lvalue, but that lvalue is not actually read from, we're just doing pointer math on it, so in theory, it should be well defined. That's just my interpretation though.
My solution involves using a null pointer to retrieve the offset to the field, so it's a bit simpler than yours as it avoids one subtraction (we'd be subtracting 0). I believe I saw some C compilers/standard libraries implementing offsetof by essentially returning the address of a field from a null pointer, which is what inspired the following solution.
fn main() {
let p: *const Baz = 0x1248 as *const _;
let p2: *const Foo = unsafe { ((p as usize) - (&(*(0 as *const Foo)).memberB as *const _ as usize)) as *const _ };
println!("{:p}", p2);
}
We can also define our own offset_of! macro:
macro_rules! offset_of {
($ty:ty, $field:ident) => {
unsafe { &(*(0 as *const $ty)).$field as *const _ as usize }
}
}
fn main() {
let p: *const Baz = 0x1248 as *const _;
let p2: *const Foo = ((p as usize) - offset_of!(Foo, memberB)) as *const _;
println!("{:p}", p2);
}
With the implementation of RFC 2582, raw reference MIR operator, it is now possible to get the address of a field in a struct without an instance of the struct and without invoking undefined behavior.
use std::{mem::MaybeUninit, ptr};
struct Example {
a: i32,
b: u8,
c: bool,
}
fn main() {
let offset = unsafe {
let base = MaybeUninit::<Example>::uninit();
let base_ptr = base.as_ptr();
let c = ptr::addr_of!((*base_ptr).c);
(c as usize) - (base_ptr as usize)
};
println!("{}", offset);
}
The implementation of this is tricky and nuanced. It is best to use a crate that is well-maintained, such as memoffset.
Before this functionality was stabilized, you must have a valid instance of the struct. You can use tools like once_cell to minimize the overhead of the dummy value that you need to create:
use once_cell::sync::Lazy; // 1.4.1
struct Example {
a: i32,
b: u8,
c: bool,
}
static DUMMY: Lazy<Example> = Lazy::new(|| Example {
a: 0,
b: 0,
c: false,
});
static OFFSET_C: Lazy<usize> = Lazy::new(|| {
let base: *const Example = &*DUMMY;
let c: *const bool = &DUMMY.c;
(c as usize) - (base as usize)
});
fn main() {
println!("{}", *OFFSET_C);
}
If you must have this at compile time, you can place similar code into a build script and write out a Rust source file with the offsets. However, that will span multiple compiler invocations, so you are relying on the struct layout not changing between those invocations. Using something with a known representation would reduce that risk.
See also:
How do I create a global, mutable singleton?
How to create a static string at compile time
import "fmt"
func zeroptr(ptr *int) {
*ptr = 0
}
func main() {
oneptr * int
*ptr = 1
fmt.Println("ptr is :", *ptr)
zeroptr(ptr)
fmt.Println("after calling zeroptr, the value of ptr is :", *ptr)
}
This does not work, I am looking for output as follows:
ptr is :1
after calling zeroptr, the value of ptr is : 0
You should use pass an &int to zeroptr, as in this example:
package main
import "fmt"
func zeroptr(ptr *int) {
*ptr = 0
}
func main() {
var ptr int
ptr = 1
fmt.Println("ptr is :", ptr)
zeroptr(&ptr)
fmt.Println("after calling zeroptr, the value of ptr is :", ptr)
}
Output:
ptr is : 1
after calling zeroptr, the value of ptr is : 0
You can see a similar example in "What's the point of having pointers in Go?", from the golang book.
What does your pointer point to? In order to manipulate the memory a pointer points to, you first need to point the pointer somewhere. Right now, your ptr is pointing to nil which is invalid. You could for instance do this:
func main() {
var foo int
var oneptr *int = &foo
*oneptr = 1
fmt.Println("oneptr is :", *oneptr)
zeroptr(oneptr)
fmt.Println("after calling zeroptr, the value of oneptr is :", *ptr)
}
For the future, please indent your code before submitting it here. You can do this with the gofmt program.
Hi everyone in Golang what will you do if you need to change the pointer (change where the pointer points to rather than change the value where this pointer points to). I know it is really easy in C++ by using reference, like"
void myFunc(Type*& ptr)
{
ptr = anotherPointer;
}
int main
{
Type* ptr = &someValue;
myFunc(ptr); // ptr is moved
}
Or equivalently in C, use pointer's pointer:
void myFunc(Type** ptrsptr)
{
*ptrsptr = anotherPointer;
}
int main
{
Type* ptr = &someValue;
myFunc(&ptr); // ptr is moved
}
I wonder if Golang has this neat feature, or if not, the only way is to set at function's return?
You can use a pointer to a pointer, just like in C
http://play.golang.org/p/vE-3otpKkb
package main
import "fmt"
type Type struct{}
var anotherPointer = &Type{}
func myFunc(ptrsptr **Type) {
*ptrsptr = anotherPointer
}
func main() {
ptr := &Type{}
fmt.Printf("%p\n", ptr)
myFunc(&ptr) // ptr is moved
fmt.Printf("%p\n", ptr)
}
The below example will change the value of variable only:
package main
import "fmt"
func main() {
value := 200
var p1 *int = &value
var p2 **int = &p1
fmt.Printf("Value of variable before updating %v and address of pointer is: %p\n", *p1, p1)
*p1 = 300
fmt.Printf("Value of variable after updating by p1 %v and address of pointer is: %p\n", *p1, p1)
**p2 = 400
fmt.Printf("Value of variable after updating by p2 %v and address of pointer is: %p\n", *p1, p1)
}
The below code will change the pointer value and also point to new address:
package main
import "fmt"
func changePointer(newP **int) {
val := 500
*newP = &val
}
func main() {
value := 200
var p1 *int = &value
fmt.Printf("Value of variable before updating %v and address of pointer is: %p\n", *p1, p1)
changePointer(&p1)
fmt.Printf("Value of variable after updating %v and address of pointer is: %p\n", *p1, p1)
}
How can I return a struct array from a .Call to a function in a C shared library and subsequently use that array in R?
For example:
typedef struct{
int thing1;
int thing2;
float thing3;
float thing4;
char thing5;
//... many more things of various simple types
} MY_STRUCT;
SEXP R_Calls_Me(SEXP args) {
// Do stuff with args...
// Create arrayOfMyStructs as what type??
return arrayOfMyStructs;
}
What type is arrayOfMyStructs such that R can use it?
It seems like a common thing one would want to do, but I cannot find any examples of this in the documentation for writing R extensions.
Typically you create list (generic vector) with the components you want to return. In your case something like
SEXP res = PROTECT(allocVector(VECSXP, 5));
SET_VECTOR_ELT(res, 0, ScalarInteger(a.thing1));
SET_VECTOR_ELT(res, 1, ScalarInteger(a.thing2));
SET_VECTOR_ELT(res, 2, ScalarReal(a.thing3));
...
UNPROTECT(1)
return res;
It is also customary to assign names to the vector, e.g.:
const char *names[5] = { "thing1", "thing2", "thing3", "thing4", "thing5" };
SEXP sNames = PROTECT(allocVector(STRSXP, 5));
for (int i = 0; i < 5; i++) SET_STRING_ELT(res, i, mkString(names[i]));
setAttrib(res, R_NamesSymbol, sNames);
UNPROTECT(1);
Note that what you are describing is not an array but a structure. Arrays are typically much easier to pass as vectors.
Probably the most natural way to do this is to use external pointers. You'll return a pointer to R and then your application code will manipulate that. A number of packages do this now, e.g., XML, h5r.
SEXP _h5R_make_ptr() {
h5_holder* holder = (h5_holder*) Calloc(1, h5_holder);
holder->id = 1;
holder->is_file = 0;
SEXP e_ptr = R_MakeExternalPtr(holder, R_NilValue, R_NilValue);
PROTECT(e_ptr);
R_RegisterCFinalizerEx(e_ptr, h5R_finalizer, TRUE);
UNPROTECT(1);
return e_ptr;
}