2

I'm trying to debug a program I'm writing that's using the libvirt library in C.

In part of the program I'm being returned the following struct:

struct virTypedParameter {
    char field[VIR_TYPED_PARAM_FIELD_LENGTH];
    int type;
    union {
        int i;
        unsigned int ui;
        long long int l;
        unsigned long long int ul;
        double d;
        char b;
        char *s;
    } value;
}

So I have a key, value, and value type. I want to be able to print these by passing them to a function.

Is there an easier way to do this other than throwing the type into a switch statement and redirecting to the proper printf statement? I've done so and it's causing a ton of warnings to pop up on compile:

void printVirTypedParameter(virTypedParameter* param) {
    printf("Param type: %d\n", param->type);
    switch(param->type) {
        case 1: //int
            printf("%s : %d\n", param->field, param->value);
            break;
        case 2: //int unsigned
            printf("%s : %u\n", param->field, param->value);
            break;
        case 3: //long long int
            printf("%s : %ld\n", param->field, param->value);
            break;
        case 4: //long long unsinged
            printf("%s : %llu\n", param->field, param->value);
            break;
        case 5: //double
            printf("%s : %f", param->field, param->value);
            break;
        case 6: //boolean (character)
            printf("%s : %c", param->field, param->value);
            break;
        case 7: //string
            printf("%s : %s", param->field, param->value);
            break;
        case 8: //param last
            printf("END_PARAMS");
}
Samuel Peter
  • 4,136
  • 2
  • 34
  • 42
user731842
  • 202
  • 2
  • 6
  • 2
    The 'struct' you're being returned isn't identifiable as C; there are too many syntax errors in it — mostly missing semicolons — plus some commentary without comment markers. Note that most types in C are unburnt — not even singed. You should be careful to use unsigned rather than unsinged. Granted, a compiler doesn't read comments for understanding, and humans can deal with transliteration errors, but they shouldn't have to. – Jonathan Leffler Sep 04 '17 at 16:07
  • 1
    Sidenote: Case 3 uses wrong format specifier for `long long int`: It should be `%lld`. – user694733 Sep 05 '17 at 07:26
  • the posted code is missing the closing brace for the `switch()` statement. – user3629249 Sep 05 '17 at 13:59
  • the definition of `VIR_TYPED_PARAM_FIELD_LENGTH` so it is unknown what the actual offset, within the struct, for all the following fields. – user3629249 Sep 05 '17 at 14:00
  • 1
    The field `type` (seems) to be limited to a small set of values. Therefore, it would be better written as an instance of an `enum` – user3629249 Sep 05 '17 at 14:03
  • for ease of readability and understanding, separate code blocks (for, if, else, while, do...while, switch, case, default) via a single blank line – user3629249 Sep 05 '17 at 14:16
  • The output from `printf()` will stay in the `stdout` buffer until an input statement is executed -or- the buffer overflow -or- `fflush( stdout );` is executed -or- the program exits. Suggest appending a '\n' to each of the format strings. – user3629249 Sep 05 '17 at 14:21

2 Answers2

5

The switch is the way to do it. But you should be using the member of the union that is appropriate for the type that you read, i.e. you should use param->value.i if you know that the type is int. This should avoid any warnings.

So for instance:

switch(param->type) {
        case 1: //int
            printf("%s : %d\n", param->field, param->value.i);
            break;
        // ...
}
Samuel Peter
  • 4,136
  • 2
  • 34
  • 42
0

The comments to the question cover the obvious problems with the OPs posted code. The following is an example of the code with all the obvious problems corrected.

#include <stdio.h>    // printf()

#define VIR_TYPED_PARAM_FIELD_LENGTH 30

enum VALID_TYPES
{
    INTEGER = 1,
    UNSIGNED_INTEGER,
    LONG_LONG_INTEGER,
    UNSIGNED_LONG_LONG_INTEGER,
    DOUBLE,
    CHAR,
    CHAR_POINTER,
    ALL_DONE
};

struct virTypedParameter
{
    char field[VIR_TYPED_PARAM_FIELD_LENGTH];
    //int type;
    enum VALID_TYPES type;
    union
    {
        int i;
        unsigned int ui;
        long long int l;
        unsigned long long int ul;
        double d;
        char b;
        char *s;
    } value;
};


// prototypes
void printVirTypedParameter( struct virTypedParameter* param);


void printVirTypedParameter( struct virTypedParameter* param)
{
    printf("Param type: %d\n", param->type);

    switch(param->type)
    {
        case INTEGER: //int
            printf("%s : %d\n", param->field, param->value.i);
            break;

        case UNSIGNED_INTEGER: //int unsigned
            printf("%s : %u\n", param->field, param->value.ui);
            break;

        case LONG_LONG_INTEGER: //long long int
            printf("%s : %lld\n", param->field, param->value.l);
            break;

        case UNSIGNED_LONG_LONG_INTEGER: //long long unsinged
            printf("%s : %llu\n", param->field, param->value.ul);
            break;

        case DOUBLE: //double
            printf("%s : %f\n", param->field, param->value.d);
            break;

        case CHAR: //boolean (character)
            printf("%s : %c\n", param->field, param->value.b);
            break;

        case CHAR_POINTER: //string
            printf("%s : %s\n", param->field, param->value.s);
            break;

        case ALL_DONE: //param last
            printf("END_PARAMS\n");
            break;

        default:
            printf( "found unexpected value in 'type' field: %d\n", param->type );
            break;
    }
}
user3629249
  • 16,402
  • 1
  • 16
  • 17