0

I've been trying to implement a generic array searcher and came across this answer, which made me think that my implementation is only valid for dynamically allocated arrays.

The implementation looks like this:

void *array_search( void *arr,
                    size_t elem_size,
                    size_t len,
                    arr_search_checker v,
                    void *match)
{
    char *p = arr;
    for(unsigned i = 0; i < len; ++i)
    {
        if(v((void *) p, match))
            return p;
        p += elem_size;
    }

    return NULL;
}

The type arr_search_checker:

typedef bool (*arr_search_checker)(void *, void *);

Having a simple structure:

struct test_struct { int i; char c; };

And a check function:

bool test_checker(void *l, void *r)
{
    struct test_struct *ls = l, *rs = r;
    return ls->i == rs->i && ls->c == rs->c;
}

And array of length len which is an array of struct test_struct one can invoke the searcher:

struct test_struct match = { .i = 5, .c = 'A' };
struct test_struct *res = array_search(array,
    sizeof(struct test_struct), len, test_checker, &match);

Is that true that this implementation of array_search is only valid for dynamically allocated arrays because of incrementation of the char pointer p by size of the single element in the array what can be dangerous for padded arrays? Or is it totally invalid?

K. Koovalsky
  • 596
  • 4
  • 17
  • This question is more about suggestions on how to improve, or how to implement than a specific problem you are having and what you tried to fix it. I believe It would really be a better fit for _[code review](https://codereview.stackexchange.com/)_. – ryyker Apr 09 '18 at 13:06

1 Answers1

0

Please state your question in the question topic.
The function array_search as valid for any arrays (don't know why dynamically allocated arrays are particular in any way). Char pointer p is incremented by elem_size. elem_size is assigned the value of sizeof(struct test_struct) in your example and that's perfectly ok. Padding has nothing to do with it. Imagine struct test_struct has some padding bytes added to it (anywhere, at the end of the structure or between any of it members). Then sizeof(struct test_struct) will be the size of the test_struct structure including the padding bytes, and p will still be increment correctly.
You may convert any pointer to void* and any pointer to char* without braking the strict aliasing rule. You cannot do arithmetic on void* pointers, that's why it gets converted to char* pointer. elem_size represents the size of a single array element in bytes, char represents one byte in memory, by doing p += elem_size; you add elem_size bytes to p (I like the form p = &p[elem_size];). The smallest addressable size in C is one byte (remember that byte may not be 8 bits) and the size of every structure or type in C must be an integral value (ie. sizeof(struct test_struct) cannot return 1,5).
For more, look at bsearch and qsort functions from standard C library. They have a very similar declaration to array_search and work with any array types, just like array_search here.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111