Determine if same pointers are passed to a macro - c++

There are set of macros, for debugging, logging, stack-trace displaying etc. One of them is like:
#define ASSERT_IF_NULL_2(_ptr1, _ptr2) \
ASSERT(_ptr1); \
ASSERT(_ptr2);
This is over simplified version of macro(s) I have written. I have custom-assertion dialog box if assertion (runtime) fails, logs such null-check failure into log file. Macros are also written such that non-pointers are checked at compile time (static-assert).
Now, I am looking for some static-assert to check if two pointers are actually same. Example:
int* ptr;
ASSERT_IF_NULL_2(ptr, ptr);
Should raise a compiler error since both arguments to macro are same. I don't care if pointers point to same memory (since that thing is runtime).
I have tried expression like:
int xx;
xx = 1 / (ptr-ptr);
xx = 1 / (&ptr - &ptr);
None of them gives divide-by-zero compiler error.
Also, I have tried with template that takes void* is template argument:
template<void* T>
class Sample{};
But it doesn't allow local-variable pointers to be passed to template non-type argument.
I am using VC9, which doesn't support constexpr keyword (even VS2012 doesn't). I tried using 'const' instead, which doesnt throw error. I also used the expression as array-size, which always results in error.
int array[(&ptr - &ptr)]; // Even with ptrdiff_t

Alright, the solution turns out to be simple. Use static_assert and Stringizing Operator (#):
#define ASSERT_TWO(a,b) static_assert((void*)#a != (void*) #b, "'" #a "' and '" #b "' are same variables passed to ASSERT_TWO.")
Demo:
int *global;
int main()
{
int *local;
ASSERT_TWO(global, local); //should pass
ASSERT_TWO(local, global); //should pass
ASSERT_TWO(global, global); //should fail
ASSERT_TWO(local, local); //should fail
(void)local; //suppress unsused warning!
}
which results in very helpful error message:
main.cpp: In function 'int main()':
main.cpp:18:5: error: static assertion failed: 'global' and 'global' are same variables passed to ASSERT_TWO.
main.cpp:19:5: error: static assertion failed: 'local' and 'local' are same variables passed to ASSERT_TWO.
Online demo.
Hope that helps.
I recall that this will not help you, as you're using VC9, but I keep this answer as it might help others. As of now, you could use other solution which generates redeclaration error which is less helpful error message compared to the static_assert message.

So you want to check if same name is passed to both arguments, right? Then this simple trick works
#define ASSERT_IF_NULL_2(_ptr1, _ptr2)\
{\
int _check_##_ptr1;\
int _check_##_ptr2;\
}\
ASSERT(_ptr1);\
ASSERT(_ptr2);
int main ()
{
int* ptr1;
int* ptr2;
ASSERT_IF_NULL_2 (ptr1, ptr1); // error: redeclaration of `int _check_ptr1'
ASSERT_IF_NULL_2 (ptr1, ptr2); // OK
}
EDIT (By OP, Ajay):
On Visual C++ compiler, we can use MS specific keyword __if_exists to give error through static-assert :
#define ASSERT_IF_NULL_2(_ptr1, _ptr2)\
{\
int _check_##_ptr1;\
__if_exists(_check_##_ptr2)
STATIC_ASSERT(false, "Same pointer passed twice")
}\
Since static_assert keyword doesnt exist for pre-VS2010 compilers, one may use custom-written STATIC_ASSERT.

Are you trying to check if the pointers point to the same memory or if they point at the same value?
In the first case
xx = 1 / (ptr-ptr);
should work.
in the second case
xx = 1 / (*ptr-*ptr);
should work.

Try one of these maybe:
ASSERT_IF_NULL(ptr1 == ptr1);
ASSERT(ptr1 != ptr2)
As pointed outby Nawaz you want a compile error so try this:
1/(ptr1 != ptr2);
1/static_cast<int>(ptr1 != ptr2);
static_assert(ptr1 != ptr2, "Pointers are different") //if you dont use c++0x look here:http://stackoverflow.com/a/1664651/258418

Related

What’s the best way to cast a function pointer from one type to another?

I’ve searched Stack Overflow for an answer, but I get nothing specific to this problem: only general cases about use of various types of cast operators.
So, the case in point is when retrieving a function address with the Windows GetProcAddress() API call, which returns a function pointer of type FARPROC, with: typedef INT_PTR (__stdcall *FARPROC)();.
The trouble is, the actual function sought rarely (if ever) has this actual signature, as shown in the MRCE code, below. In this code, I have shown a variety of different attempts to convert the returned value to a function pointer of the appropriate type, with all but the fourth method commented out:
#include <Windows.h>
#include <iostream>
typedef DPI_AWARENESS_CONTEXT(__stdcall* TYPE_SetDPI)(DPI_AWARENESS_CONTEXT); // Function pointer typedef
static DPI_AWARENESS_CONTEXT __stdcall STUB_SetDpi(DPI_AWARENESS_CONTEXT) { return nullptr; } // Dummy 'stub' function
static DPI_AWARENESS_CONTEXT(__stdcall* REAL_SetDpi)(DPI_AWARENESS_CONTEXT) = STUB_SetDpi; // Func ptr to be assigned
using std::cout; using std::endl;
int main()
{
HINSTANCE hDll = LoadLibrary("User32.dll");
if (!hDll) {
cout << "User32.dll failed to load!\n" << endl;
return 1;
}
cout << "User32.dll loaded succesfully..." << endl;
// (1) Simple assignment doesn't work ...
// REAL_SetDpi = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
// (2) Using 'C'-style cast does work, but it is flagged as 'evil' ...
// REAL_SetDpi = (TYPE_SetDPI)GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
// (3) Using reinterpret_cast: seems OK with clang-cl but MSVC doesn't like it ...
// REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(GetProcAddress(hDll,
// (4) Using a temporary plain "void *": OK with MSVC but clang-cl complains ...
void* tempPtr = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(tempPtr);
// (5) Using a union (cheating? - but neither clang-cl nor MSVC give any warning!) ...
// union {
// intptr_t(__stdcall* gotProc)(void);
// TYPE_SetDPI usrProc; // This has the 'signature' for the actual function.
// } TwoProcs;
// TwoProcs.gotProc = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
// REAL_SetDpi = TwoProcs.usrProc;
if (REAL_SetDpi == nullptr) cout << "SetThreadDpiAwarenessContext function not found!" << endl;
else cout << "SetThreadDpiAwarenessContext function loaded OK!" << endl;
FreeLibrary(hDll);
return 0;
}
The various error/warning messages given by the clang-cl and native MSVC compiler, for each of the 5 options are as follows:
// (1) Simple assignment doesn't work ...
REAL_SetDpi = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
clang-cl -> error : assigning to 'DPI_AWARENESS_CONTEXT (*)(DPI_AWARENESS_CONTEXT) __attribute__((stdcall))'
(aka 'DPI_AWARENESS_CONTEXT__ *(*)(DPI_AWARENESS_CONTEXT__ *)') from incompatible type 'FARPROC'
(aka 'long long (*)()'): different number of parameters (1 vs 0)
Visual-C -> error C2440: '=': cannot convert from 'FARPROC' to
'DPI_AWARENESS_CONTEXT (__cdecl *)(DPI_AWARENESS_CONTEXT)'
message : This conversion requires a reinterpret_cast, a C-style cast or function-style cast
This error is (of course) expected, but the one confusing thing to me is why MSVC shows my function as __cdecl when I have explicitly declared it __stdcall?
// (2) Using 'C'-style cast does work, but it is flagged as dangerous ...
REAL_SetDpi = (TYPE_SetDPI)GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
clang-cl -> warning : use of old-style cast [-Wold-style-cast]
Visual-C -> warning C4191: 'type cast': unsafe conversion from 'FARPROC' to 'TYPE_SetDPI'
warning C4191: Calling this function through the result pointer may cause your program to fail
Generally, I endeavour to completely avoid old, ‘C’-style casts in my code! Where I am forced to do cast between ‘unrelated’ objects, I use explicit reinterpret_cast operators, as these are far easier to track down in code if problems arise. So, for case 3:
// (3) Using reinterpret_cast: seems OK with clang-cl but MSVC doesn't like it ...
REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(GetProcAddress(hDll, "SetThreadDpiAwarenessContext"));
clang-cl -> No error, no warning!
Visual-C -> warning C4191: 'reinterpret_cast': unsafe conversion from 'FARPROC' to 'TYPE_SetDPI'
Calling this function through the result pointer may cause your program to fail
Here, the MSVC warning is pretty much the same as for the C-style cast. Maybe I could live with this, but case 4 makes things more interesting:
// (4) Using a temporary plain "void *": OK with MSVC but clang-cl complains ...
void* tempPtr = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
REAL_SetDpi = reinterpret_cast<TYPE_SetDPI>(tempPtr);
clang-cl -> warning : implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension
[-Wmicrosoft-cast]
warning : cast between pointer-to-function and pointer-to-object is incompatible with C++98
[-Wc++98-compat-pedantic]
Here, MSVC gives no warning – but I feel I’m simply ‘fooling’ the compiler! I can’t see how this can have any different overall effect than the code in case 3.
// (5) Using a union (cheating? - but neither clang-cl nor MSVC give any warning!) ...
union {
intptr_t(__stdcall* gotProc)(void);
TYPE_SetDPI usrProc; // This has the 'signature' for the actual function.
} TwoProcs;
TwoProcs.gotProc = GetProcAddress(hDll, "SetThreadDpiAwarenessContext");
REAL_SetDpi = TwoProcs.usrProc;
I did post this as an answer (now retracted), to which #formerlyknownas_463035818 pointed out that this is officially Undefined Behaviour and/or disallowed in C++ (the link given by the aforementioned commentator).
Which option do I currently use?
Well, as my software is specifically Windows-oriented, I use the last (option 4) for two reasons: (1) the clang-cl warning is the ‘least scary’; and (2) I like to think that MSVC is probably the best ‘mediator’ for compiling/building Windows apps.
EDIT: Since first posting this question, and having 'reviewed' the various comments and suggestions made, I have now changed all
instances of this type of cast (that is, from a function pointer
loaded via GetProcAddress) in my code to using the following
conversion 'function', defined in my global header file:
template<typename T> T static inline FprocPointer(intptr_t(__stdcall* inProc)(void)) {
__pragma(warning(suppress:4191)) // Note: no semicolon after this expression!
return reinterpret_cast<T>(inProc);
}
This allows for easy/rapid location of any such casts, should I need (or wish) to change the way they work in future.
Why does it matter?
Maybe it doesn’t! However, elsewhere in my code, I have come across an unexpected crash, when using function pointers loaded via GetProcAddress() - not any standard WinAPI calls, but functions from my own DLLs, loaded as plug-in modules. The code snippet below shows a potential case-in-point:
// --------------------------------------------------------------------------------------------------------------------
// These two routines are the 'interceptors' for plug-in commands; they check active plug-ins for handlers or updaters:
static int plin; //! NOTA BENE: We use this in the two functions below, as the use of a local 'plin' loop index
// is prone to induce stack corruption (?), especially in MSVC 2017 (MFC 14) builds for x86.
void BasicApp::OnUpdatePICmd(uint32_t nID, void *pUI)
{
//! for (int plin = 0; plin < Plugin_Number; ++plin) { // Can cause problems - vide supra
for (plin = 0; plin < Plugin_Number; ++plin) {
BOOL mEbl = FALSE; int mChk = -1;
if ((Plugin_UDCfnc[plin] != nullptr) && Plugin_UDCfnc[plin](nID, &mEbl, &mChk)) {
CommandEnable(pUI, mEbl ? true : false);
if (mChk >= 0) CmdUISetCheck(pUI, mChk);
return;
}
}
CommandEnable(pUI, false);
return;
}
void BasicApp::OnPluginCmd(uint32_t nID)
{
//! for (int plin = 0; plin < Plugin_Number; ++plin) { // Can cause problems - vide supra
for (plin = 0; plin < Plugin_Number; ++plin) {
piHandleFnc Handler = nullptr; void *pParam = nullptr;
if ((Plugin_CHCfnc[plin] != nullptr) && Plugin_CHCfnc[plin](nID, &Handler, &pParam) && (Handler != nullptr)) {
Handler(pParam);
return;
}
}
return;
}
Note that, Plugin_UDCfnc and Plugin_CHCfnc are arrays of function pointers, loaded as described above.
And, finally, what was my question, again?
Two-fold:
Is it ‘safe’ to ignore the warnings?
Is there a better way, using the Standard Library (I’m still getting used to using this)
– maybe something like std::bind()?
Any help, suggestions or recommendations will be greatly appreciated.
EDIT: I use the native MSVC compiler for my “Release” builds (with /Wall), and a few specific warnings explicitly disabled (locally) in code. From time to time, I run my entire code base through the clang-cl compiler, to look for other warnings of possible dodgy code (very useful, actually).
I think C/C++ are lacking a generic function pointer type, like void* as a generic object pointer type.
Generally, converting from one function pointer into another is supported, provided that you don't call the wrong function pointer type. See [expr.reinterpret.cast]/6:
A function pointer can be explicitly converted to a function pointer of a different type.
A warning that is issued when casting one function pointer type to another is generally useful. Having such casting might cause a call to a function with the wrong signature. Such a problem might affect only a certain CPU architecture, or be noticed only with certain OS builds, so it might not be apparent after initial testing. The Standard just says unspecified, see [expr.reinterpret.cast]/6:
Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
Whether void* can be converted to function pointer type and whether it even has enough bits is implementation specific. True for Windows, though. I wouldn't endorse Windows-specific habits for a generic problem. See
[expr.reinterpret.cast]/8:
Converting a function pointer to an object pointer type or vice versa is conditionally-supported.
Type punning with unions raises an issue with strict aliasing (What is the strict aliasing rule?), so not a good way to outsmart a compiler.
So, live with local warning suppression near your GetProcAddress calls, or in a GetProcAddess wrapper. Use reinterpret_cast.
If you're going to use a helper function that casts one function type into another without a warning, be sure to use it only in GetProcAddress-like scenario, when you use some generic signature to temporary store function pointer, but that signature is not an actual signature -- not to call a function pointer by a not intended type.
Sorry.

C++ insert function pointer into memory

I am trying to overwrite a char and a function pointer on the stack. Based on what I found on this question (How can I store a value at a specific location in the memory?) I was able to figure out how to overwrite the character. My problem now is that I get a compile error saying I am casting it wrong.
void foo(char letter);
void bar(char letter);
void function1()
{
void (*pointer)(char);
pointer = foo;
letter = 'B';
function2();
(*pointer)(letter);
}
void function2()
{
int number; // Used in omitted code
*(char *)(&number + 75) = 'A';
*(void (*)(char)) (&number + 42) = &bar; // This is the line with the error
}
The first injection works but the second one gives me a compile error.
I am running Redhat Linux using a g++ compiler. The error I get from the compiler is:
"cannot convert ‘void (*)(char)’ to ‘void(char)’ in assignment"
If I change that line to *(void(char)) then the compiler says:
"invalid cast to function type ‘void(char)’"
What is the proper syntax for this?
(This is modified code from a school security assignment, I'm not writing malware)
Your goal is to write the address of pass to memory, so why are you casting (&number + 13) to a function pointer? Just do what you did before:
*(long *)(&number + 13) = (long)&pass;
And you won't get a compiler error. As to what will happen when this undefined behavior is invoked, you'll just have to see.
Edit: As #DavidGrayson pointed out, if we deference the right side of the equation, we'd get the contents of the function, not its pointer. So we have to cast it to a POD type, not a pointer.

Validate an argument is ARRAY type in c/c++ pre processing macro on compile time [duplicate]

This question already has answers here:
Array-size macro that rejects pointers
(9 answers)
Closed 4 years ago.
Is there any way to validate on compile time in a c macro that an argument is an array ?
e.g in this two macros:
#define CLEAN_ARRAY(arr) \
do { \
bzero(arr, sizeof(arr)); \
} while (0)
And
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
I tried something using CTC(X) macro , but couldn't find any way to validate/warn if arr isn't an array.
Here's a solution in pure C which invokes no undefined behavior:
#define IS_INDEXABLE(arg) (sizeof(arg[0]))
#define IS_ARRAY(arg) (IS_INDEXABLE(arg) && (((void *) &arg) == ((void *) arg)))
If you need to ensure that the value is an array (then cause a compile time error if not), you can simply use it as an initializer to an enum statement (or a static variable), like this:
static int __ ## arg ## _is_array = IS_ARRAY(arg); // works for an array, fails for pointer.
I'm not entirely sure what will happen with VLA's, but playing around a bit should find that answer out rather fast.
Old answers:
Since this is tagged C (and GCC), I will attempt a solution here:
#define IS_ARRAY(arg) __builtin_choose_expr(__builtin_types_compatible_p(typeof(arg[0]) [], typeof(arg)), 1, 0)
Another solution, using C11's _Generic feature & typeof:
#define IS_ARRAY(arg) _Generic((arg),\
typeof(arg[0]) *: 0,\
typeof(arg[0]) [sizeof(arg) / sizeof(arg[0])]: 1\
)
Basically, all it does is use some fancy features of GCC to determine if the type of the argument is compatible with an array of the type of the argument's elements. It will return 0 or 1, and you could replace the 0 with something that creates a compile time error if you wish.
A pure C99 solution:
enum { must_be_an_array_1 = ((void *) &(arr)) == ((void *) (arr)) };
typedef char must_be_an_array_2[((void *) &(arr)) == ((void *) (arr)) ? 1 : -1];
This exploits the fact that the address of an array is the same as the address of its first member, and that an enum member must be an integral constant. If the compiler is smart enough to tell that a pointer-to-a-pointer has a distinct address, it will choke on the second statement.
We still need the first statement because otherwise a compiler with support for runtime sized arrays (e.g. gcc 4.7) will perform the address comparison at runtime and invoke undefined behaviour as the size of the runtime array is negative (e.g. under gcc the program segfaults).
Full program:
#include <strings.h>
#define CLEAN_ARRAY(arr) \
do { \
enum { must_be_an_array_1 = ((void *) &(arr)) == ((void *) (arr)) }; \
typedef char must_be_an_array_2[((void *) &(arr)) == ((void *) (arr)) ? 1 : -1]; \
bzero(arr, sizeof(arr)); \
} while (0)
int main() {
int arr[5];
CLEAN_ARRAY(arr);
int *ptr;
CLEAN_ARRAY(ptr); // error: enumerator value for ‘must_be_an_array’ is not an integer constant
return 0;
}
How to validate in c macro the argument is of ARRAY type
Use std::is_array inside of the macro. Or forget themacro and just use std::is_array.
Concerning ARRAY_SIZE,
constexpr size_t size(T const (&)[N])
{
return N;
}
As per my comment:
sizeof((x)[0]) will give an error if the type is not an "indexable" type - however, if it happens to be a pointer, it will happily take that. And also, if there is an operator[] for the type of x.
It is quite hard in C to do this, but C++ may allow some template type solutions (I don't actually know how to do that, as I've never tried to do that, or anything similar with templates).
(for C++) my current clear macro in VS2010 is:
#define CLEAR(v) do { __pragma(warning(suppress: 4127 4836)) typedef std::remove_reference< decltype(v)>::type T; static_assert( std::is_pod<T>::value || (__has_trivial_constructor(T) && __has_trivial_destructor(T)), "must not CLEAR a non-POD!" ); static_assert( !std::is_pointer<T>::value, "pointer passed to CLEAR!" ); memset(&(v), 0, sizeof(v)); } while(0)
You can make up your variant using stuff in type_traits header.
A formatted verision with explanations:
#define CLEAR(v) \
do { \
__pragma(warning(suppress: 4127 4836)) \
typedef std::remove_reference< decltype(v)>::type T; \
static_assert( \
std::is_pod<T>::value \
|| (__has_trivial_constructor(T) && __has_trivial_destructor(T)), \
"must not CLEAR a non-POD!" ); \
static_assert( !std::is_pointer<T>::value, "pointer passed to CLEAR!" ); \
memset(&(v), 0, sizeof(v)); \
} while(0)
outer do-while to make it usable like a genuine function in all places including if/else.
Remove_reference is needed so it works with lvalues, decltype alone makes int* and int*& different and is_pointer reports false for the latter.
The is_pod check is good for general, the additional condition allows struct A1 : A; case work where A is POD and A1 adds only more POD members. For is_pod purpose it's false, but to clear it makes the same sense.
is_pointer check guards the expected mistype when you get the indirection wrong on pointer or pass an address of struct in confusion. Use = NULL to clear a pointer please. ;-)
The __pragma is there to suppress L4 warnings that are issued otherwise.
As far as I can tell, nobody has yet provided a way to ensure that the argument of ARRAY_SIZE is actually an array.
<Edit>
Found Array-size macro that rejects pointers
Original answer follows:
</Edit>
The macro I use for this is:
#define ASSERT_EXPR(condition,return_value) \
(((char(*)[(condition)?1:-1])0)?(return_value):(return_value))
Principle:
0 is casted to pointer to array (with size of one (condition true) or minus one (condition false, generate error)). This null-pointer is then used as the condition of a ternary operator. Although we know, that it will always only evaluate the third operand (null-pointer means false), the second operand is also return_value -- this way the resulting type is the same as the type of return_value.
Using this, (and the IS_ARRAY from Richard J. Ross III's answer) I can define my safe ARRAY_SIZE macro as follows:
#define IS_ARRAY(arg) __builtin_choose_expr(__builtin_types_compatible_p(typeof(arg[0]) [], typeof(arg)), 1, 0)
#define ARRAY_SIZE(x) ASSERT_EXPR(IS_ARRAY(x), (sizeof(x)/sizeof((x)[0])) )
I didn't manage to get it working with Richard J. Ross III's two other IS_ARRAY variants, but that might be my (or gcc's) fault...
In C, this should work:
#define VALIDATE_ARRAY(arr) (void)(sizeof((arr)[0]))
int *a, b;
int main() {
VALIDATE_ARRAY(a);
VALIDATE_ARRAY(b);
return 0;
}
This program will fail to compile, because b is not an array. This is because b[0] is an invalid. It won't distinguish pointers from arrays - I don't think you can do that.
This form of the macro can only be used inside a function. If you want to use it outside a function, you'll have to modify it (e.g. to declare an extern array).

C++ equivalent to taking address of a constant?

I've got some code written in C (specifically targeted to gcc) that needs to also compile as C++ (g++). I've run into a construct I'm having difficulty dealing with.
There are some macros used in a lot of places which basically take the address of a constant, although they also work on non-constants. The construct winds up looking something like this:
int *iptr = (&(int){5});
What this essentially lets happen is a constant be specified, and then a pointer to that constant can be taken for use in a function that requires an int pointer, but only a constant is specified. Multiple values can also be specified inside the curley braces to construct an actual temporary array, too. And it works great.
Problem in, g++ does not like this at all, throwing
error: non-lvalue in unary `&'
Update: Looks like I can take the address of a constant in C++ by doing something like:
const int & ref = 5;
So that's the starting point for the direction I'm trying to take.
The following appears to work in both C and C++, although it only compiles under C++11, not C++03.
#ifdef __cplusplus
#define A(type,x) (&(const type &)(type)x)
#define Of(...) { __VA_ARGS__ }
#else
#define A(type,x) (&(type){x})
#define Of(...) __VA_ARGS__
#endif
Test Code:
int test(const void *ptr,int len) {
char *str = (char *)ptr;
int i;
for (i=0;i<len;i++) {
printf("%02X ",str[i]);
}
printf("\n");
return 0;
}
int main() {
test(A(int,5),4);
test(A(x,Of(5,6)),8);
int i=1,j=2;
test(A(x,Of(i,j)),8);
}
Edit: Whoops, not quite there. Doesn't work if the type is a pointer!
test(A(char *,9),4);
=>
error: invalid cast of an rvalue expression of type 'char*' to type 'const char*&'
Note: I'm abandoning this approach in favor of a different approach (compiling C code as C and linking it via C++) but will keep this answer up in case it is useful to somebody.

How to use a Judy array

I am interested in Judy Arrays and try to use it. But i had unable to do any useful thing using it. Every time it gives me casting errors.. Sample c++ code and the error given below.
#include "Judy.h"
#include <iostream>
using namespace std;
int main()
{
int Rc_int; // return code - integer
Word_t Rc_word; // return code - unsigned word
Word_t Index = 12, Index1 = 34, Index2 = 55, Nth;
Word_t PValue; // pointer to return value
//Pvoid_t PJLArray = NULL; // initialize JudyL array
Pvoid_t JudyArray = NULL;
char String[100];
PWord_t _PValue;
JSLI( JudyArray, _PValue, (uint8_t *) String);
return(0);
} // main()
This gives me the error
m.cpp: In function ‘int main()’:
m.cpp:19: error: invalid conversion from ‘long unsigned int**’ to ‘void**’
m.cpp:19: error: initializing argument 1 of ‘void** JudySLIns(void**, const uint8_t*, J_UDY_ERROR_STRUCT*)’
Please anyone help me to figure out what is the error what i'm doing..
Thanks
According to the documentation, you have the _PValue and JudyArray parameters reversed. Make your call look like this:
JSLI( _PValue, JudyArray, (uint8_t *) String);
Also, try not compiling it as C++ code. So far, your test uses no C++ features. I bet it will compile as C code. It looks like JudyArray relies on the fact that C will do certain kinds of implicit conversions between void * and other pointer types.
If this is the case, I'm not sure what to do about it. The error messages you're getting tell me that JSLI is a macro. In order to fix the error message you have in the comments on this answer, you'd have to reach inside the macro and add a typecast.
These kinds of implicit conversions are allowed in C because otherwise using malloc would always require ugly casts. C++ purposely disallows them because the semantics of new make the requirement that the result of malloc be cast to the correct type unimportant.
I don't think this library can be used effectively in C++ for this reason.
It seems that, you pass JudySLIns(void**, const uint8_t*, J_UDY_ERROR_STRUCT*) a wrong parameter, the first one, you'b better check it!
For integer keys there is a C++ wrapper at http://judyhash.sourceforge.net/