Is it a good idea to use varargs in a C API to set key value pairs?

前端 未结 7 2655
情书的邮戳
情书的邮戳 2021-02-20 11:47

I am writing an API that updates a LOT of different fields in a structure.

I could help the addition of future fields by making the update function variadic:

<         


        
7条回答
  •  春和景丽
    2021-02-20 12:38

    A lot of folks here have suggested passing the # of parameters, however others rightly note that this leads to insidious bugs where the # of fields changes but the count passed to the vararg function doesn't. I solve this in a product by using null termination instead:

    send_info(INFO_NUMBER,
              Some_Field,       23,
              Some_other_Field, "more data",
              NULL);
    

    That way, when copy and paste programmers inevitably copy it, they're not likely to mess up. And more importantly, I'm not likely to mess it up.

    Looking back at the original problem, you have a function that must update a structure with a lot of fields, and the structure will grow. The usual method (in the Win32 and MacOS classic APIs) of passing in data of this sort to a function is by passing in another structure (can even be the same structure as what you're updating), ie:

    void update(UPDATESTRUCTURE *update_info);

    to use it, you would populate the fields:

    UPDATESTRUCTURE my_update = {
        UPDATESTRUCTURE_V1,
        field_1,
        field_2
    };
    update( &my_update );
    

    Later on when you add new fields, you can update the UPDATESTRUCTURE definition and recompile. By putting in the version #, you can support older code that doesn't use the new fields.

    A variant on the theme is to have a value for fields you don't want updated, like KEEP_OLD_VALUE (ideally this will be 0) or NULL.

    UPDATESTRUCTURE my_update = {
        field_1,
        NULL,
        field_3
    };
    update( &my_update);
    

    I don't include a version because I take advantage of the fact when we increase the # of fields in UPDATESTRUCTURE, the extra fields will be initialized to 0, or KEEP_OLD_VALUE.

提交回复
热议问题