0

Considering the code as follows:

void get_value_by_peek_name(json_object *json_obj, const char *peak_name, void **value) {
    json_object *value_obj;
    if (json_object_object_get_ex(json_obj, peak_name, &value_obj))
        if (json_object_is_type(value_obj, json_type_double))
            sscanf(json_object_to_json_string(value_obj), "%lf", *value);
}

This implementation, as expected, generates a warning:

format ‘%lf’ expects argument of type ‘double *’, but argument 3 has type ‘void *’

I am looking for a suggestion to better implement this function and, of course, avoid the warning above.

Elsewhere, considering also the code:

double timestamp;
void *holder;

// some other code...
// response_obj already initialized 
get_value_by_peek_name(response_obj, "timestamp", &holder);
timestamp = *((double *) holder);
printf("- timestamp: %lf\n", timestamp);

Is there a good way to make this code more elegant, without declaring explicitly the void pointer holder but by using directly timestamp to hold the value?

vdenotaris
  • 13,297
  • 26
  • 81
  • 132
  • 1
    In the line `sscanf(json_object_to_json_string(value_obj), "%lf", *value);`, change to `(double *)*value`, and make sure you have `void *holder = &timestamp;`, and get rid of the line `timestamp = *((double *) holder)` – M.M Aug 25 '15 at 08:53
  • `holder` is not initialized. – vdenotaris Aug 25 '15 at 08:53
  • If `holder` is not initialized then you are passing an uninitailized pointer to sscanf – M.M Aug 25 '15 at 08:53
  • Yes, but the `sscanf` writes correctly the value. – vdenotaris Aug 25 '15 at 08:54
  • No it doesn't . You possibly mean it *appears* to write the value when you ran the code, but in fact you are seeing undefined behaviour. – M.M Aug 25 '15 at 08:55
  • Weird. I have tested the code above and it works correctly. – vdenotaris Aug 25 '15 at 08:55
  • 3
    Testing is no guarantee that your code is correct. Try `char *p = malloc(3); p[4] = 'x';` and see what happens – M.M Aug 25 '15 at 08:56
  • Thanks for your advice. Which one is the right way to initialize it? I am currently just using `holder` as temp variable to pass as argument to the function `get_value_by_peek`, even if would be better avoid to use it (the second point of the question). – vdenotaris Aug 25 '15 at 09:04
  • See my comment above with the code in it . If you want to avoid the temp variable you will have to change the function definition, as shown in alk's example. – M.M Aug 25 '15 at 09:08
  • It works and made my mind more clear. Thanks ;) – vdenotaris Aug 25 '15 at 09:12
  • Check this [similar post](http://stackoverflow.com/questions/3039513/type-safe-generic-data-structures-in-plain-old-c/31654151#31654151) –  Aug 25 '15 at 13:01

1 Answers1

3

avoid the warning above.

  1. Define get_value_by_peek_name() to take a void* as last parameter:

    void get_value_by_peek_name(json_object * json_obj, const char * peak_name, void * value)
    
  2. Make sure holder points to a double (or at least to enough memory, which as well is properly aligned to hold a double), then

  3. properly cast the pointer in the call to sscanf() before dereferencing it:

    sscanf(json_object_to_json_string(value_obj), "%lf", *((double**)value));
    
alk
  • 69,737
  • 10
  • 105
  • 255
  • wouldn't the cast `(double *)value` be enough (assuming you call `get_value_by_peek_name( ....., &timestamp );`) ? – Ingo Leonhardt Aug 25 '15 at 08:51
  • @IngoLeonhardt that would be one approach, alk is suggesting a different approach – M.M Aug 25 '15 at 08:54
  • 1
    No, as `value` had been initilalised on call as `&holder`. This applies to the way the OP calls `get_value_by_peek_name()`. – alk Aug 25 '15 at 08:55