4 ms·
"(but try not to cast functions)". Try not to cast at all, of course, but especially not functions.
by neonscribe 9y ago
"(but try not to cast functions)". Try not to cast at all, of course, but especially not functions.
- geofft 9y agoI was going to post something about how you need to cast function pointers to use dlsym(), which returns a void * (since it doesn't know statically what the type of function you're asking for is, let alone that it's a function at all). You'd do something like void *mylib = dlopen("mylib.so"); int (*myfn)(int) = (int (*)(int))dlsym(mylib, "myfn"); And I was also going to comment on how casts between data pointers (including void * ) and function pointers are undefined behavior in the C spec, but conformance to POSIX requires that to work because how else are you going to use dlsym. But then I looked up the example in the POSIX.1-2004 dlsym manpage, which does this bizarre thing instead: http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html http://pubs.opengroup.org/onlinepubs/009695399/functions/dls... int (*fptr)(int); *(void **)(&fptr) = dlsym(handle, "my_function"); and there's a RATIONALE section in that man page explaining why, and the Linux dlsym man page calls it out too: http://man7.org/linux/man-pages/man3/dlopen.3.html#EXAMPLE http://man7.org/linux/man-pages/man3/dlopen.3.html#EXAMPLE /* According to the ISO C standard, casting between function pointers and 'void *', as done above, produces undefined results. POSIX.1-2003 and POSIX.1-2008 accepted this state of affairs and proposed the following workaround: *(void **) (&cosine) = dlsym(handle, "cos"); This (clumsy) cast conforms with the ISO C standard and will avoid any compiler warnings. The 2013 Technical Corrigendum to POSIX.1-2008 (a.k.a. POSIX.1-2013) improved matters by requiring that conforming implementations support casting 'void *' to a function pointer. Nevertheless, some compilers (e.g., gcc with the '-pedantic' option) may complain about the cast used in this program. */ and indeed, the POSIX.1-2013 man page does the natural thing, saying "This standard requires this conversion to work correctly on conforming implementations": http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlsym.html http://pubs.opengroup.org/onlinepubs/9699919799/functions/dl... I wonder if there are any C compilers that actually optimize casts between data and function pointers as if they could be undefined (not counting hardware architectures where such casts literally don't work because they're in different address spaces).
- neonscribe 9y agoWhat sort of optimization might be possible? Also, is there any active development today on separate instruction and data address space architectures?
- kragen 9y agoIt probably no longer makes sense to use AVRs instead of ARMs (or MIPS or whatever) for cost reasons, but there are still a lot of things out there that use them for backward-compatibility reasons — most notably most Arduinos — and lots of people are still doing active development for those things, and probably will be until the mid-2020s, if not later. People are still building new 8051-based systems, for heaven's sake, although not using discrete 8051 chips.
- sly010 9y agoAtmel's AVRs are harward architecture (separate data and code address space) and are almost exclusively programmed using gcc. They are widely used too.
- dfox 9y agoThe reason for casts between data and function pointers is not about separate data and code spaces (that much), but about: 1) supporting architectures where code and data pointers have different size. One might think of various Hardvard architecture microcontrollers, but most C memory models for real mode x86 have this feature. 2) environments where code pointers essentially convey capability and thus have to be created by the OS in order to be usable (this typically involves indirect call instructions reading from some part of memory that is not otherwise accessible to user space at all)
- nwellnhof 9y agoInterestingly, this hack has caused problems with gcc4 on s390: https://git.gnome.org/browse/libxml2/tree/include/libxml/hash.h?h=v2.9.7#n32 https://git.gnome.org/browse/libxml2/tree/include/libxml/has... . The comment claims it violates C's aliasing rules.
- hinkley 9y agoI had the idea, years ago when I still thought some day I'd write a programming language, that somewhere between type inference and programmatic type inspection that there is space for promoting a type based on your inspection. Especially if you're using Static Single Assignment inside of your compiler. For instance: Object foo = inputArgument1; if (foo typeof function) { // in this block foo is a function. foo(bar); } Where this breaks down on legibility is when people rely too much on inductive reasoning (you can only get into this block if three other things are true... except now there's a bug so that's no longer true) or they keep reassigning to 'foo' willy nilly through their code. But if those are the sorts of people who lose out to the benefit of everyone else, I'm not even sad.
- greiskul 9y agoKotlin does that with it's smart cast feature: https://kotlinlang.org/docs/reference/typecasts.html https://kotlinlang.org/docs/reference/typecasts.html It's really great actually, and the IDE also helps by marking foo slightly different inside the block, and if you mouseover to check for it's type it says what it is, and that it's because of a smart cast.
- hinkley 9y agoI have a suspicion that the Jetbrains guys were reading the same language design sources that I was. There are several other features like the ? operator that I saw in a small language first (called Nice). Daniel Bonnoit did a good job of articulating some of his design choices, especially optional types.