Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

void* considered harmful

Name: Anonymous 2012-12-22 14:24


#include "stdio.h"

void *lsearch(void *addr, void *key, int arraysize, int typesize) {
        for (int i = 0; i < arraysize; i++) {
                if (addr[typesize * i] == *key) return &addr[typesize * i];
        }
        return NULL;
}
 
int main() {
        int is[] = {1,2,3,4,5};
        int i = 5;
        void *address = lsearch(is, &i, 5, sizeof(int));
        printf("%p", address);
        return 0;
}



why do I get these errors?:


generics.c: In function ‘lsearch’:
generics.c:5:11: warning: dereferencing ‘void *’ pointer [enabled by default]
generics.c:5:29: warning: dereferencing ‘void *’ pointer [enabled by default]
generics.c:5:3: error: void value not ignored as it ought to be
generics.c:5:3: error: void value not ignored as it ought to be
generics.c:5:47: warning: dereferencing ‘void *’ pointer [enabled by default]

Name: sage 2012-12-22 14:27

sage

Name: Anonymous 2012-12-22 14:34

Read K&R!

Name: Anonymous 2012-12-22 15:35

memcpy(void_ptr, rvalue, void_ptr_width);

Name: Anonymous 2012-12-22 17:08

>why do I get these errors?

i think because void value is not ignored as it ought to be

Name: Anonymous 2012-12-22 17:30

You can't write &addr[typesize * i] because indexing arrays accounts for the number of bytes each value in the array contains. That is to say, &array[2] is equal to array + 8 when array contains 4-byte values (like long ints.)

To do this with void pointers of some known type size, you have to resort to pointer arithmetic and write addr + typesize * i.

You can't dereference two void pointers and compare them like this, because C can't know how much bytes to compare without knowing how big the type is. You can, however, compare memory blocks of some known size using memcmp.

This code gives no warnings on my end:

#include "stdio.h"

void *lsearch(void *addr, void *key, int arraysize, int typesize) {
    int i;
    for (i = 0; i < arraysize; i++) {
        if (memcmp(addr + typesize * i, key, typesize) == 0)
            return addr + typesize * i;
    }
    return NULL;
}

Name: Anonymous 2012-12-22 18:16

Just use C++ templates. void* is slow and error-prone.

Name: Anonymous 2012-12-22 18:23

>>6
This code gives no warnings on my end
Pointer arithmetic on void pointers yields undefined behavior, so I wouldn't count on your code for a lot.

Name: Anonymous 2012-12-22 18:44

This makes me wonder if it is possible to implement this function in portable c. Sure you could change void* to char* and use memcmp, but does c even specify that each item in an item_t array occupies exactly sizeof(item_t) bytes?

Name: Anonymous 2012-12-22 19:51

You can't just directly access a void pointer. The compiler has no idea what the size of the thing it points to is. You have to cast it to something.

Name: DA STANDARD 2012-12-23 0:08


void *lsearch(const void *key, const void *base, size_t nmemb, size_t size,
        int (*compar) (const void *, const void *))
{
    const char *ptr;

    for (ptr = base; nmemb-- ptr += size)
        if (!compar(ptr, key))
            return (void *) ptr;
    return 0;
}

Name: Anonymous 2012-12-23 0:48

void CONSIDERED JEWISH

Name: Anonymous 2012-12-23 9:58

>>8
Whoops, you're right. Something like this should do the trick, apparently:

(*(char *)&addr) + typesize * i

Name: Anonymous 2012-12-23 11:58

I mean:

(*(char **)&addr) + typesize * i

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List