8

I use an external C library in my C++ program and the library uses a callback function, that must return void*. The library checks if return value is not NULL, which means success.

So what is the best way to tell it that all is fine?

I use:

return reinterpret_cast<void*>(1);

but it looks ugly...

Edit: thanks for reply, i will stay with this:

static int success;
return &success;
Kris Harper
  • 5,672
  • 8
  • 51
  • 96
ShPavel
  • 962
  • 1
  • 10
  • 17

5 Answers5

12
static int dummy;
return &dummy;

Strictly speaking, static is probably not required, but it feels a bit gauche to return a pointer to a local that's going out of scope.

EDIT: Note @sharptooth's comment. Strictly speaking, static is required.

Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • 5
    Without `static` you'd get a dangling pointer and using (even copying) such pointer is UB. – sharptooth Jan 23 '13 at 10:56
  • @sharptooth: I would have thought that copying a pointer would be fine, as long as it was constructed correctly (i.e., was valid at some point). Note that I'm not disagreeing, just surprised. – Marcelo Cantos Jan 23 '13 at 11:00
  • 2
    Yes, this is a common misconception http://stackoverflow.com/a/1866543/57428 and it just works on most architecture, yet it is UB. – sharptooth Jan 23 '13 at 11:05
  • @MarceloCantos: `static void* success = reinterpret_cast(&success);` allows a `return success;` afterward :D – Matthieu M. Jan 23 '13 at 13:15
4

Using reinterpret_cast is as clean as you could get to. The problem is crafting such pointers from int literals yields undefined behavior - the Standard forbids use of pointers that are not null and are not pointing to properly allocated objects. The Standard-compliant way would be to have some variable (perhaps a file scope variable would be the most convenient) and return its address.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 1
    That is incorrect. `reinterpret_cast(1)` is well-defined code to create an implementation-defined pointer value according to the implementation-define mapping between pointers and integers. (see C++ standard clause [expr.reinterpret.cast]/5) – Bart van Ingen Schenau Jan 23 '13 at 11:11
  • @Bart van Ingen Schenau: Excellent, but if it yields an invalid pointer you get UB. – sharptooth Jan 23 '13 at 11:25
  • @BartvanIngenSchenau: if nothing else, the UB is that the caller is going to compare the pointer value to a null pointer. I'm not certain whether returning an invalid pointer value counts as "using" it ([basic.stc.dynamic.deallocation]/4), but comparing it to null does. It's also not clear to me whether the implementation-defined mapping between `void*` and `int` is required to include a pointer value corresponding to *every* value of `int`, or if the implementation is allowed to define that `1` doesn't have a value at all, and the cast itself will trap or whatever. – Steve Jessop Jan 23 '13 at 11:32
  • @SteveJessop: The problem that I have with that is implementation define (as of C++11) whether the result of `reinterpret_cast(1)` results in an *invalid pointer value*. As far as I can tell, prior to C++11, this was not specified (and I would assume, part of the mapping between integers and pointers). – Bart van Ingen Schenau Jan 23 '13 at 12:04
  • @BartvanIngenSchenau: IIRC the C standard at least defined what valid pointer was (`(void *)1` was not listed). I wonder why it wasn't copy'n'pasted into C++ standard if it is as you claim (I didn't have time to check it). – Maciej Piechotka Jan 23 '13 at 13:27
3

I'd probably write something like:

return const_cast<void*>(""); // non-null pointer, referand doesn't matter

Perhaps the callback function has a pointer input guaranteed not to be null. If so then you could return that.

reinterpret_cast<void*>(1) is supposed to look ugly, because it's not guaranteed to work. Most architectures don't mind you doing that, but

  • the standard doesn't actually guarantee that you can use a pointer value that isn't the address of any object (or a null pointer, or one-off-the-end of an array).
  • the standard doesn't guarantee that reinterpret_cast<void*>(1) is not a null pointer, that's implementation-defined.

I doubt there really is an implementation in which your function returns null by accident, but there's allowed to be. Imagine a hypothetical implementation in which the CPU's own addressing is 4-bit rather than 8-bit. Of course the implementer would still choose CHAR_BIT == 8, and all pointers in C++ would be 8-bit aligned. Then the implementation could legally and fairly reasonably map from pointers to integers by leaving the bit pattern unchanged, and from integers to pointers by zeroing the last bit. Alternatively it could right-shift and left-shift by 1 bit. The standard requires that pointer -> integer -> pointer restores the original value, but doesn't require that integer -> pointer -> integer does.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • tried it: error: invalid conversion from ‘const void*’ to ‘void*’ – ShPavel Jan 23 '13 at 11:18
  • @user286215: oops. You could const_cast it. All you need, though, is an object that still exists as long as the caller will use the return value. So find a non-const one for preference, failing that a const one like `""` and cast. – Steve Jessop Jan 23 '13 at 11:19
  • Neither is `const_cast("")` guarantied to work, since the `""` is a constant string. Or, am I wrong? – BЈовић Jan 23 '13 at 11:48
  • @BЈовић there was other suggestion earlier. it is ok now. – ShPavel Jan 23 '13 at 11:54
  • @BЈовић: there's no explicit prohibition against taking a pointer-to-non-const to an object defined as const. I suspect that the same issue applies to C++ as I asked about for C recently (http://stackoverflow.com/questions/14437699). I also suspect the answer is the same, that although nothing explicitly says you can do it, there is text that forbids modifying (but not reading) such objects that would be redundant if you can't validly get a non-const reference to them in the first place. But I haven't scoured the C++ standard for details yet. I'm pretty sure the intention is that you can. – Steve Jessop Jan 23 '13 at 12:26
2

How about

return this;

as an easy way to return a valid pointer that is guaranteed to be non-NULL?

simonc
  • 41,632
  • 12
  • 85
  • 103
1

If it were me, I would use:

return (void*)1;

Simple and beautiful.

I prefer value 1 (as you used in question) over any other value, because other values can be interpreted in some way (which is not good). If all you want is to return a non-zero value (non-null pointer) it is better that you use a value that nothing special can be extracted from it.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72