Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Double reference

57 views
Skip to first unread message

Queequeg

unread,
Nov 7, 2018, 8:37:19 AM11/7/18
to
Hi,

I have a code similar to this:

#v+
void fn1(const void *p, size_t sz) { /* ... */ }

void fn2(int &iref)
{
int *iptr(&iref);
fn1(&iptr, sizeof(iptr));
}

void fn3()
{
int i;
fn2(i);
/* ... */
}
#v-

In other words, I want to reference (verb) the reference (noun), getting
its pointer, and then pass this pointer as a stream of bytes to another
function, which reads the `sz` bytes from area pointed to by `p`. I need
it to pass the address of `i` across threads over socket-based IPC, so
another thread will be able to use it (it's a guarantee that `i` will be
in scope as long as the thread is accessing it -- fn3 will not return).

This code works, but is it possible to implement fn2() it in one line,
without creating a temporary variable?

--
https://www.youtube.com/watch?v=9lSzL1DqQn0

Bo Persson

unread,
Nov 7, 2018, 9:05:25 AM11/7/18
to
Probably not.

You are not allowed to take the address of a temporary (an rvalue), so
yoy have to store the pointer somewhere first to get an lvalue. Like in
your example.


Bo Persson

Manfred

unread,
Nov 7, 2018, 11:42:19 AM11/7/18
to
On 11/7/2018 2:37 PM, Queequeg wrote:
> Hi,
>
> I have a code similar to this:
>
> #v+
> void fn1(const void *p, size_t sz) { /* ... */ }
>
> void fn2(int &iref)
> {
> int *iptr(&iref);
> fn1(&iptr, sizeof(iptr));
> }
>
> void fn3()
> {
> int i;
> fn2(i);
> /* ... */
> }
> #v-
>
> In other words, I want to reference (verb) the reference (noun), getting
> its pointer, and then pass this pointer as a stream of bytes to another
> function, which reads the `sz` bytes from area pointed to by `p`.
In C++ you cannot get a pointer to a reference. You get a pointer to the
referenced object instead - as Bjarne says, 'a reference is not an
object', so you can't take its address.
In your code:
> int *iptr(&iref);

iptr is not a pointer to iref, it is a pointer to 'i' inside fn3().
Moreover, when you pass &iptr to fn1() you are passing a pointer to
iptr, i.e. an object inside fn2(), so from your description it looks
like you are creating a dangling pointer as soon as you leave fn2().

I need
> it to pass the address of `i`
If you need to pass the address of `i` you should pass iptr, not &iptr,
unless I am missing something.

across threads over socket-based IPC, so
> another thread will be able to use it (it's a guarantee that `i` will be
> in scope as long as the thread is accessing it -- fn3 will not return).
>
> This code works, but is it possible to implement fn2() it in one line,
> without creating a temporary variable?
>
Depending on how the receiving side uses the pointer, what would be
wrong with fn1(&i, sizeof(i)) ?

Ralf Fassel

unread,
Nov 7, 2018, 12:37:15 PM11/7/18
to
* quee...@trust.no1 (Queequeg)
--<snip-snip>--
| void fn2(int &iref)
| {
| int *iptr(&iref);
| fn1(&iptr, sizeof(iptr));
| }
--<snip-snip>--
>
| This code works, but is it possible to implement fn2() it in one line,
| without creating a temporary variable?

I'd say

void fn2(int &iref)
{
fn1(&iref, sizeof(int*));
}

should work...

In your fn2(), you are passing the address of the temporary _pointer_,
not the address of the pass-by-reference-variable, which seems wrong to
me. Instead it should be fn1(iptr, sizeof(iptr)).

R'

Queequeg

unread,
Nov 8, 2018, 5:28:03 AM11/8/18
to
Stefan Ram <r...@zedat.fu-berlin.de> wrote:

>>Distribution through any means other than regular usenet
>
> Sorry! I am using a new version of my Usenet client.
> It seems to have copied some of the headers into the body.

It didn't, your headers seem to be correct (and tin displays them
correctly), although some lines in X-Copyright are indented with
tab and some with spaces. RFC1036 says it's correct:

The Internet convention of continuation header lines (beginning
with a blank or tab) is allowed.

--
https://www.youtube.com/watch?v=9lSzL1DqQn0

Queequeg

unread,
Nov 8, 2018, 5:42:01 AM11/8/18
to
Ralf Fassel <ral...@gmx.de> wrote:

> | This code works, but is it possible to implement fn2() it in one line,
> | without creating a temporary variable?
>
> I'd say
>
> void fn2(int &iref)
> {
> fn1(&iref, sizeof(int*));
> }
>
> should work...

But it's not the same.

I modified it:

#v+
void fn1(const void *p, size_t sz)
{
const unsigned char *b(static_cast<const unsigned char *>(p));

printf("Pointer value to be transferred:");
for (size_t i(0); i < sz; ++i)
printf(" %02x", b[sz - i - 1]);
printf("\n");
}

void fn2(int &iref)
{
int *iptr(&iref);
printf("Address of iptr: %p\n", &iptr);
printf("Address of iref: %p\n", &iref);
fn1(&iptr, sizeof(iptr));
fn1(&iref, sizeof(int*));
}

int main()
{
int i(0x12345678);
fn2(i);
return 0;
}
#v-

Running it gives:

#v+
Address of iptr: 0x7eb0c574
Address of iref: 0x7eb0c584
Pointer value to be transferred: 7e b0 c5 84
Pointer value to be transferred: 12 34 56 78
#v-

Addresses of iptr (temporary pointer) and reference (`i` in main) are
different (and should be), but only the first call to fn1 (where it reads
the temporary pointer) gives the proper address of `i` in main (address
that is recreated in another thread). Reading data pointed to by &iref
gives the value of `i` itself (which in this case is of the same size as
the pointer-to-i).

> In your fn2(), you are passing the address of the temporary _pointer_,
> not the address of the pass-by-reference-variable, which seems wrong to
> me. Instead it should be fn1(iptr, sizeof(iptr)).

Hmm... I need to read the temporary pointer contents, that is -- know what
it points to. After fn1() terminates, the pointer is not needed anymore,
because its contents has been transferred.

I don't want to transfer contents of `i`, I want to transfer its address.
`i` is modified in `main` and I need to see these changes in thread.

This is a simplified example, in reality `i` is not int, but a class.

--
https://www.youtube.com/watch?v=9lSzL1DqQn0

Queequeg

unread,
Nov 8, 2018, 5:56:32 AM11/8/18
to
Bo Persson <b...@gmb.dk> wrote:

> You are not allowed to take the address of a temporary (an rvalue), so
> yoy have to store the pointer somewhere first to get an lvalue. Like in
> your example.

Makes sense. Thanks!

--
https://www.youtube.com/watch?v=9lSzL1DqQn0

Ralf Fassel

unread,
Nov 8, 2018, 10:24:24 AM11/8/18
to
* quee...@trust.no1 (Queequeg)
| Ralf Fassel <ral...@gmx.de> wrote:
| > void fn2(int &iref)
| > {
| > fn1(&iref, sizeof(int*));
| > }
| >
| > should work...
>
| But it's not the same.

Not the same as ... what?

| void fn1(const void *p, size_t sz)
| {
| const unsigned char *b(static_cast<const unsigned char *>(p));
>
| printf("Pointer value to be transferred:");
| for (size_t i(0); i < sz; ++i)
| printf(" %02x", b[sz - i - 1]);
| printf("\n");
| }

Why don't you simply use p here?

printf("Pointer value to be transferred: %p\n", p);

Why dereference it? Of course, if you dereference a pointer, you get
the contents of what it points to, that's the nature of pointers...

You're interested in the address of 'i' in main, correct?
If so, just use that address!

#include <cstdio>

void f1(void *p) {
printf("f1: address is %p\n", p);
}
void f2(int &num) {
printf("f2: address is %p\n", &num);
f1(&num);
}
int main() {
int i;
f1(&i);
f2(i);
}
// g++ -o t t.cc
// ./t
// f1: address is 0x7ffff51fd61c
// f2: address is 0x7ffff51fd61c
// f1: address is 0x7ffff51fd61c


HTH
R'

Queequeg

unread,
Nov 8, 2018, 5:35:16 PM11/8/18
to
Ralf Fassel <ral...@gmx.de> wrote:

> | > void fn2(int &iref)
> | > {
> | > fn1(&iref, sizeof(int*));
> | > }
> | >
> | > should work...
>>
> | But it's not the same.
>
> Not the same as ... what?

Not the same as reading the pointer value. fn1() will read data pointed to
by &iref, which is the contents of the integer, not its address.

> | printf("Pointer value to be transferred:");
> | for (size_t i(0); i < sz; ++i)
> | printf(" %02x", b[sz - i - 1]);
> | printf("\n");
> | }
>
> Why don't you simply use p here?
>
> printf("Pointer value to be transferred: %p\n", p);

Still, because it's not the same as what this code does. In my simplified
example this function just prints bytes to be transferred, real function
encapsulates it and sends over a socket to another thread.

> Why dereference it? Of course, if you dereference a pointer, you get
> the contents of what it points to, that's the nature of pointers...

I need exactly that.

> You're interested in the address of 'i' in main, correct?
> If so, just use that address!
>
> #include <cstdio>
>
> void f1(void *p) {
> printf("f1: address is %p\n", p);
> }
> void f2(int &num) {
> printf("f2: address is %p\n", &num);
> f1(&num);
> }
> int main() {
> int i;
> f1(&i);
> f2(i);
> }

Yes, with printfs it's simple, but how would you do it with write(), which
expects an area of memory and its size (that's why fn1() expects the same)?

--
https://www.youtube.com/watch?v=9lSzL1DqQn0

Manfred

unread,
Nov 9, 2018, 8:09:17 AM11/9/18
to
On 11/8/2018 11:35 PM, Queequeg wrote:
>> Why dereference it? Of course, if you dereference a pointer, you get
>> the contents of what it points to, that's the nature of pointers...
> I need exactly that.
>
>> You're interested in the address of 'i' in main, correct?
>> If so, just use that address!
>>
>> #include <cstdio>
>>
>> void f1(void *p) {
>> printf("f1: address is %p\n", p);
>> }
>> void f2(int &num) {
>> printf("f2: address is %p\n", &num);
>> f1(&num);
>> }
>> int main() {
>> int i;
>> f1(&i);
>> f2(i);
>> }
> Yes, with printfs it's simple, but how would you do it with write(), which
> expects an area of memory and its size (that's why fn1() expects the same)?

#include <cstdio>

void f1(void *p) {
int fd = ...;
printf("f1: address is %p\n", p);
write(fd, &p, sizeof(p));
0 new messages