6 ms·
If your C compiler doesn't complain bitterly to you about an incompatible pointer type on that assignment, get a better C compiler. If your C compiler does com
by pklausler 10y ago
If your C compiler doesn't complain bitterly to you about an incompatible pointer type on that assignment, get a better C compiler. If your C compiler does complain bitterly about it, heed those warnings or expect no sympathy.
If you write this in production code, and don't get sent home that day in tears, your company's code review process has failed.
- akkartik 10y agoNo warnings (-W -Wall) with gcc 4.2.1 on OSX :/ gcc 4.8.4 on Ubuntu 14.04 Trusty still gives no warnings, but gives a different result: $ gcc -W -Wall x.c -lm $ a.out (0.99)^100: 0.366032 (0.99)^100: inf clang 3.4 on Ubuntu 14.04: $ clang -W -Wall -fsanitize=undefined x.c -lm $ a.out (0.99)^100: 0.366032 (0.99)^100: inf :(
- jcranmer 10y agoIt's not practical to make this a warning because of, e.g., dlsym (which is actually worse because void * and void (*)() aren't necessarily compatible types). Another thing which makes this sort of thing difficult to warn in is the brokenness of autoconf. Autoconf checks that your system has memcpy (or anything that you check via AC_TRY_LINK) by compiling this program: void memcpy(); int main() { (void)memcpy(); }
- jandrese 10y agoWait, undefined parameters are guaranteed to be zero in C? That's something I wouldn't have expected. Certainly nothing I would rely on in my own code.
- dllthomas 10y agoNo, not at all. It doesn't run the program, the program isn't correct, it just compiles and links. Symbols don't know their types (... with some caveats about name mangling in some languages).
- inlined 10y agoIn C, a function with no parameters is variadic. You need to add "void" to preclude parameters. This is one of the few breaking changes in C++ where no parameters means no parameters.
- dllthomas 10y agoTrue, but I'm not seeing the relevance. Just an interesting aside?
- int_19h 10y agoIt's legal to declare an external function symbol without specifying the parameters, so long as you actually match the types of real parameters (after all the standard conversions for functions with such prototypes are taken into account, like char -> int; and excluding some corner cases, like varargs) when you call it. If you don't actually call it, it's not U.B. However, the snippet above is still broken in that respect, because it doesn't match the return type of memcpy - and that is U.B.
- dllthomas 10y ago> It's legal to declare an external function symbol without specifying the parameters, so long as you actually match the types of real parameters Yes. And the call here does not match the types of the real parameters, even before we consider the return type.
- coldtea 10y ago>If your C compiler doesn't complain bitterly to you about an incompatible pointer type on that assignment, get a better C compiler. Yeah? So which compiler do you have in mind exactly we should use?
- MaulingMonkey 10y ago> If your C compiler doesn't complain bitterly to you about an incompatible pointer type on that assignment, get a better C compiler. The example code uses C style casts, which is C-speak for "fuck off compiler I know what I'm doing." I'd like to see what warnings your compiler produces. VS2015 /W4 /ANALYZE produces nothing, and neither do clang nor GCC from the looks of it. That people C cast without knowing what they're doing is rather unfortunate tragedy. That this is a common enough problem, that the Win32 API is littered with backwards compatability hacks where someone C-casted away ABI differences turns it into a statistic. > If you write this in production code, and don't get sent home that day in tears, your company's code review process has failed. Assuming we're talking "well meaning newbie" instead of "sanity hating self-flagellating freak and/or undefined behavior worshiping cultist", I prefer to carefully explain that they've invoked undefined behavior, that undefined behavior leads to crunching to find optimizer induced heisenbugs in the weeks before we ship, and to impress upon them that this is why we never cast away even "trivial" and "minor" function pointer differences. And then, when they ask what the correct thing to do is, point out the API docs and header both have this little "WINAPI" annotation they can use. Hey! No more casts! Easier than the casts too. Win/win. However, if we are talking about the "sanity hating self-flagellating freak and/or undefined behavior worshiping cultist", I can only recommend nuking the site from orbit. It's the only way to be sure. If their home isn't part of the radioactive crater, you didn't use large enough nukes, and your company's code review process has failed.
- quotemstr 10y agoI'd hate to work at a company with a blanket prohibition on dirty tricks like this. On rare occasions, there are good reasons to use hacks, and I'd hope my coworkers would at least be open to an attempt at justification. Sometimes silly newbie mistakes actually end up being the right thing to do in rare, specialized circumstances and in experienced hands.
- wahern 10y agoI can't ever imagine a scenario where a hack _like_ _that_ is acceptable. If you need something like that, just drop down to assembly. It's more portable (in the sense that you're coding to an interface), infinitely more clear about what you're doing and and how you're doing it, much less likely to break, and when it does break is likely to break loudly. Even if you've never done a lick of assembly programming (I haven't done much) it'd still be infinitely preferable, even if you had to support a dozen architectures with two dozen different function proxies. "Hack" is a very broad term. By some definitions a significant chunk of extant code qualifies as a hack. But whatever the definition, a hack still implies some quantum of legitimacy. There's nothing legitimate in using function type punning as a way to reorder or control argument values. Not unless this was 1969, where there was precisely one C compiler, used by precisely one guy, and where such code was expected to be thrown out in short order, never to infect code that executed in other than identical circumstances.
- _RPM 10y agoThey are not many C compilers that are widely used in the wild. So, if I had to guess the average C programmer is using either GCC, Microsoft's C Compiler, or Clang.
- pavanky 10y agoThe latest GCC and CLANG compilers do not seem to complain with this code. What might be a better compiler?
- pjc50 10y agoSometimes you just need to cast and assume that you've been given the right thing. Such as when going anywhere near a Windows message loop. And sometimes you need to do terrifying, nonportable, ugly hacks in order to get something specific to work. My own contribution to this field is an ARM stack unwinder that requires only one __asm__ inline in order to get the link register and does everything else by interpreting instructions.