Get a struct based on member values

吃可爱长大的小学妹 提交于 2021-01-28 07:21:00

问题


I have a huge struct array and I created different function to get the struct pointer based on a member's value:

typedef struct {
    uint32_t a;
    uint32_t b;
    uint32_t c;
    uint32_t d;
} test_t;

test_t test[10]; // Initialized somewhere else

static test_t* __get_struct_by_a(uint_32_t a) {
    for (uint32_t i = 0; i < 10; i++) {
        if (test[i].a == a)
            return &test[i];
    }
    return NULL;
}

static test_t* __get_struct_by_b(uint_32_t b) {
    ...
}

Is there an easy way to tackle this in C instead of create a lookup function for every member?


回答1:


Following is one way to write a general function to get (find) your first matching struct member.

I tried to keep consistent with your sample code, adding a few #include directives that may be necessary, and a typical fixed-array size #define for TEST_SIZE so that you don't use hard-coded values for the loop indices.

#include <stddef.h>
#include <stdio.h>
#include <string.h>

typedef struct {
    uint32_t a;
    uint32_t b;
    uint32_t c;
    uint32_t d;
} test_t;

test_t test[10]; // Initialized somewhere else
#define TEST_SIZE (sizeof(test)/sizeof(test[0]))

static test_t* __get_struct_by_offset(const void* value_ptr, const size_t offset, const size_t field_size)
{
    for (uint32_t i = 0; i < TEST_SIZE; i++)
    {
        if (0 == memcmp(value_ptr, ((unsigned char*)&test[i])+offset, field_size))
        {
            return &test[i];
        }
    }
    return NULL;
}

You would use it like this:

    uint32_t a_value_to_find = 5; /* example field "a" value to find */
    uint32_t b_value_to_find = 10; /* example field "b" value to find */
    test_t* test_ptr;

    /* find specified value for field "a" */
    test_ptr = __get_struct_by_offset(&a_value_to_find, offsetof(test_t, a), sizeof(a_value_to_find));

    /* find specified value for field "b" */
    test_ptr = __get_struct_by_offset(&b_value_to_find, offsetof(test_t, b), sizeof(b_value_to_find));

It's your responsibility to ensure that the data types for *value_ptr and the field at the specified offset are identical, and therefore of the same size (field_size).

To simplify the usage, you could write some macros as shorthand for these calls. For example:

#define GET_A(value) __get_struct_by_offset(&value, offsetof(test_t, a), sizeof(value))
#define GET_B(value) __get_struct_by_offset(&value, offsetof(test_t, b), sizeof(value))

The queries for "a" and "b" are then simplified to:

    /* find specified value for field "a" */
    test_ptr = GET_A(a_value_to_find);

    /* find specified value for field "b" */
    test_ptr = GET_B(b_value_to_find);


来源:https://stackoverflow.com/questions/43220558/get-a-struct-based-on-member-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!