[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Newbie: how to handle different prototypes?
From: |
Paul Eggert |
Subject: |
Re: Newbie: how to handle different prototypes? |
Date: |
Thu, 23 Jun 2005 17:22:11 -0700 |
User-agent: |
Gnus/5.1006 (Gnus v5.10.6) Emacs/21.4 (gnu/linux) |
Ralf Wildenhues <address@hidden> writes:
> * address@hidden wrote on Wed, Jun 22, 2005 at 10:17:02PM CEST:
>> For example, on linux the scandir prototype is:
>>
>> int scandir(const char *dir, struct dirent ***namelist,
>> int(*select)(const struct dirent *),
>> int(*compar)(const struct dirent **, const struct dirent **));
>>
>> and on darwin it's:
>>
>> int
>> scandir(const char *dirname, struct dirent ***namelist,
>> int (*select)(struct dirent *),
>> int (*compar)(const void *, const void *));
>>
>> I.e. the const is missing from darwin's 3rd parameter.
>
> Can't you just ignore this difference in your program? If you pass a
> select function which eats a const argument, you are within ANSI C
> bounds in either case.
Sorry, that won't work in general.
(Putting my language-lawyer hat on.)
On darwin, you'd be passing (int (*) (struct dirent *)) to (int (*)
(struct dirent const *)), and C89 and C99 both say that two function
types are compatible only if their arguments are compatible, and that
(struct dirent const *) is not compatible with (struct dirent *).
There is an exception for pointers; e.g., you are allowed to assign a
(T *) value to a (T const *) variable. But this exception does not
apply to multiple levels (e.g., you can't assign (T **) to (T const
**). In particular, it does not apply when assigning a (T1 (*) (T2
const *)) value to a (T1 (*) (T2 *)) variable.
Arguably this is a botch. There are some cases that are safe that C
does not allow. Perhaps the best known is assigning a (T **) value to
a (T const * const *) variable. (I think C++ fixes this latter
botch.) But the botch is part of Standard C and we have to work
around it in the portable code that we write.
(Language-lawyer hat off.)