On 27/08/18 17:45, Bart wrote:
> On 27/08/2018 15:22, David Brown wrote:
>
>>> Apparently C uses void(*)(void) for this purpose, although it appears to
>>> still require a cast to that pointer type.
>>
>> Where did you get the idea that C uses "void(*)(void)" for this purpose?
>
>
> ME [12-AUG-18 Mixed Arithmetic]:
> >> How would YOU rewrite a table like this of mixed function pointers:
> >>
> >> void *table[] = {malloc, realloc, free, printf, puts};
>
> BEN:
> > typedef void func(void);
> >
> > func *table[] = {
> > (func *)malloc, (func *)realloc, (func *)free, (func *)printf,
> (func *)puts
> > };
>
You asked Ben how /he/ would write it. If you had asked me, I'd
probably have said much the same. (Keith's alternative is a little more
advanced, and a little safer.) That is because I know it works on gcc
(it's documented in the manual), and I am confident it would work on
non-gcc compilers that I sometimes use. But I also know it is not
guaranteed by the C standards - there is no common function pointer type
in standard C. "void (*)(void)" is a type that will work well for most
compilers for targets where all function pointers have the same size.
Few, if any, compilers/processors have different sized function pointers
except for "near/far" style extensions. Most of the details here are
implementation-dependent.
So again you are leaping from one example to "C does it this way".
>
>>>
>>> I would also have used that, except that (1) a cast is still need; (2)
>>> such a pointer could be also be a valid function pointer type, it is not
>>> a generic type.
>>
>> This is /generated/ C code we are still talking about, not manually
>> written C code?
>
> The cast has to be in the original source.
There does not need to be a correlation like this between source
language and the generated C code. This is a completely artificial
constraint that you have put in.
>
> If that's the case, my answers are (1) So what? and (2)
>> So what?
>
> It's like using char* to do the job of void*.
"char*" can sometimes do a similar job to "void*". "void*" cannot do
the job of "void (*)(void)". I don't see the similarity.
>
> I'm surprised you don't get that.
>
>> It's your language, you can call your types whatever you want there.
>> But you can't call them something and expect that this somehow makes
>> them the same as a C type of the same name.
>
> In modern processors there's no reason why you can't cast a void* to
> function pointer or vice versa, as they are almost certain to be the
> same size.
As I said, that is simply not true.
There are lots of processors with different sized pointers for function
and data pointers - new, current processors used in microcontrollers, as
well as a variety with different "memory model" support. You probably
remember that from your DOS days - this sort of thing is not gone from
programming. (Unlike hacks such as near/far pointers, banking, etc.,
there is no problem or inconvenience about having different sized
pointers for functions and data - unless you make unnecessary and
potentially incorrect assumptions.)
>
> Bizarrely, C allows casting between function pointers and ints, but not
> between function pointers and ordinary pointers!
Yes - if the implementation allows it, and the integer type is big
enough. You can't do much with the converted result (unless the
implementation gives you more features).
>
> Unless the ordinary pointer has the value 0, then casting between a
> function pointer and (void)*0 IS allowed.
>
> Who makes up this stuff?
Some of it certainly seems a little weird, or a missed opportunity.
>
> (BTW I think I've just found a way around the problem: you can cast from
> from pointer to function pointer VIA an int cast. Although it will need
> to be an int matching the size of the pointers of either side. (If the
> two pointer types are a different size, then there's a genuine problem.)
>
> So, apparently, it can be done. In which case why the need to go to such
> lengths?)
C lets you do a lot of things without the behaviour being defined in the
standards. If the compiler says its allowed, then that's fine - but it
is not defined behaviour standard C. Maybe it is portable enough for
your needs.
Using the suggested "void (*)(void)" type would be better, however -
even if that may also need casts.
>
>> The way to stop people telling you you are doing daft things in your C
>> code is to listen to others and stop doing daft things - not to stop
>> writing C code.
>
> This group is more like a secret society than anything else. with lots
> of arcane, made-up rules, initiation procedures and a hierarchy of
> members. Plus all their complicated tools with their 1001 settings.
> [More than that actually. Anyone outside that clique, have a read of
> Asimov's story /Profession/ to get a better idea of what I'm talking
> about.]
>
It's a strange sort of secret society that goes to such an effort to
tell you how it all works, explain all the rules, give reasons for some
of the rules (when we can figure them out ourselves), and tell you again
and again how to use these complicated tools.
> People just want to run their low level programs on their machine of
> choice; why do they have to do battle with the C language, C compilers,
> C options and the clc cartel?
>
People /do/ write and run low-level programs in C all the time (as well
as high-level programs and everything in between). People are
successful with C when they decide to work /with/ the language and the
tools, instead of /against/ them.
> This is why there need to be modern alternatives - not the even more
> bloated ones - that don't consist of 90% ancient baggage.
>
The success of C has shown that there simply is not such a need.
There is a need for safer and more powerful languages for low-level
programming - but I don't think you'd like them either. They are even
less "transparent" than C, and have more features.