Re: void pointer arithmetic
From: nospam (h.b.furuseth(nospam)_at_usit.uio(nospam).no)
Date: 11/16/03
- Next message: Anupam: "Re: struggling with strings"
- Previous message: Joe Wright: "Re: Structures, Pointer and gets"
- In reply to: Alex Fraser: "void pointer arithmetic"
- Next in thread: Alex Fraser: "Re: void pointer arithmetic"
- Reply: Alex Fraser: "Re: void pointer arithmetic"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 16 Nov 2003 20:02:31 +0100
Alex Fraser wrote:
> From searching Google Groups, I understand that void pointer
> arithmetic is a constraint violation, which is understandable.
Yup.
> However, generic functions like qsort() and bsearch() must in essence
> do exactly this,
No, what these functions do to compare the objects depends on the
original data type of the objects and their semantics. See below.
> In a few posts I read, it was suggested to avoid void pointer
> arithmetic by casting to a char pointer, and performing arithmetic on
> that (in multiples of sizeof(original_type)).
You could, but it's usually cleaner to just cast to pointers the
original type and let the compiler do the sizeof for you.
As for doing pointer arithmetic on the results: If all the pointers
point into the same array, and you really want to sort the pointers by
their index into that array, yes, then you can do that. However,
usually you'll want to do something quite else, e.g.:
static int str_qcmp(const void *a, const void *b)
{
char *const *ap = a;
char *const *bp = b;
return strcmp(*ap, *bp);
}
...
char *arr[] = { "foo", "bar", "baz" };
qsort(arr, sizeof(arr)/sizeof(*arr), sizeof(*arr), str_qcmp);
/* arr = { "bar", "baz", "foo" } */
> I am quite sure this would work on many implementations (where the
> casts are no-ops),
Never mind that. If casts are not no-ops, the casts will modify the
representations of the pointer as appropriate. Unless you make
the mistake of telling the compiler that some data has another type
than it really has, for example by casting the _function pointer_
to another type. For example, I've seen programs that did this:
static int foo_qcmp(struct foo *a, struct foo *b);
...
qsort(..., (int (*)(const void*, const void*)) foo_qcmp);
Now qsort will pass void pointers to foo_qcmp, but foo_qcmp thinks it is
receives struct foo pointers, so it doesn't convert them from void* to
struct foo*. That fails if void* and struct foo* have different
representations or are passed in different ways to functions.
> Thus the pointer is cast through the sequence
> original_type* -> void* -> char* -> void* -> original_type*.
The standard allows this, because char* and void* have the same
representation and alignment requirements. However,
original_type* -> void* -> original_type* is quite enough.
-- Hallvard
- Next message: Anupam: "Re: struggling with strings"
- Previous message: Joe Wright: "Re: Structures, Pointer and gets"
- In reply to: Alex Fraser: "void pointer arithmetic"
- Next in thread: Alex Fraser: "Re: void pointer arithmetic"
- Reply: Alex Fraser: "Re: void pointer arithmetic"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|