- "C Is The Greenest Programming Language" by: Chris Lott - 1 Update
- Inline functions and locals - 15 Updates
- Can anyone improve this ? - 3 Updates
| legalize+jeeves@mail.xmission.com (Richard): Jan 17 09:28PM [Please do not mail me a copy of your followup] Tim Rentsch <tr.17687@z991.linuxsc.com> spake the secret code >Lisp machines are special purpose hardware. Smalltalk VMs >run on standard hardware, much like Java bytecode interpreters >do today. I was thinking of the Smalltalk workstations from the 80s like those made by Tektronix. I don't think they used a VM, but ran on the bare metal. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Terminals Wiki <http://terminals-wiki.org> The Computer Graphics Museum <http://computergraphicsmuseum.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
| Juha Nieminen <nospam@thanks.invalid>: Jan 17 05:38AM > sites. But it quickly became clear that it is useless and unnecessary in > this role. As a consequence, its role was refocused to being a "ODR > defeater" - a completely different purpose. And as a side note, the C standard also added support for 'inline' functions, except that it's a different and very weird version of it that to this day I still don't fully understand. It's like an 'inline' that's *not* an "ODR defeater". (It's so confusing that the vast, vast majority of C programmers just write "static inline" to get around the confusing part.) |
| David Brown <david.brown@hesbynett.no>: Jan 17 08:12AM +0100 On 17/01/2022 06:38, Juha Nieminen wrote: > *not* an "ODR defeater". (It's so confusing that the vast, vast majority > of C programmers just write "static inline" to get around the confusing > part.) Yes, "inline" functions in C are a bit odd, and the semantics are not the same as in C++. As you say, the most common usage (and the only way I use it) is to write "static inline" for functions to replace what might pre-C99 have been a function-like macro. The "inline" here is not actually very significant - any decent C compiler will make its own decisions about actual inlining optimisations, so a plain "static" function would have the same effect. To me, at least, the "static inline" is a documentation of how you see the function and expect it to be used. <https://en.cppreference.com/w/c/language/inline> To add to the complication, gcc had "inline" as an extension prior to C99, and it had slightly different semantics. (A number of gcc C89 extensions became part of C99, sometimes with changes.) For "static inline" functions there is no difference, but there are differences for "extern inline" and other combinations. This reinforces the benefits of sticking to "static inline" in C. <https://gcc.gnu.org/onlinedocs/gcc/Inline.html> |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 16 11:51PM -0800 On 1/16/2022 11:12 PM, David Brown wrote: > function would have the same effect. To me, at least, the "static > inline" is a documentation of how you see the function and expect it to > be used. [...] Imvvvho, using inline is almost akin to almost begging the compiler to actually inline the function. It certainly can say f-you, and give the programmer the proverbial middle finger at the same time! For some reason it kind of makes me think of the register keyword... Now, it would be funny if a compiler would output something like: this function cannot be inlined, go ahead and try turning on link time optimization, and try again? ;^) |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Jan 16 11:53PM -0800 On 1/16/2022 9:38 PM, Juha Nieminen wrote: > *not* an "ODR defeater". (It's so confusing that the vast, vast majority > of C programmers just write "static inline" to get around the confusing > part.) Yes, you are right. `inline` is clearly an "ODR defeater" in C++, but in C... not so much. Firstly, `static inline` is a separate story. Most of the time `static` is all that's needed. In a quality compiler `static inline` is always redundant. It is 100% equivalent to plain `static`. There's never any tangible reason to use `static` and `inline` together. (Unless one wants to add `inline` for purely aesthetic reasons - to express how they feel about that function.) The only thing that compiler needs to be able to inline a function call is access to the function's definition, to the full function's body. Once it can see the body, it can analyze and inline the calls (if it decides to inline). `static` functions are always defined inside their TUs, which means that they are already as inlinable as they can ever be. Declaring them `inline` on top of `static` achieves absolutely nothing. So, the only tangible use of `inline` is with external linkage functions. External linkage implies that if an inline function ends up with a regular body, it should be one unique body in the whole program. And, thanks to that, the function will have unique address identity: same address in all TUs. This is the objective. And this is where C and C++ take drastically different paths to that objective. C++ achieves the above automatically through "generate them all; let linker sort them out" approach: compiler nonchalantly emits bodies for external linkage inline functions in different TUs, then linker discards all same-named bodies except one (see "weak symbols"). C, on the other hand, continues to stick to pedantically manual approach to ODR: it is the user's responsibility to ensure existence and uniqueness of a regular body generated for an inline function (just in case that body becomes necessary). The user chooses the TU for that body and the user triggers it by using the `extern inline` combination. So, yes, in C `inline` is not really an "ODR defeater". `inline` definitions in C do not emit function bodies, which means that there's nothing to defeat. `extern inline` declaration does emit a function body, but the burden of making it (and making it only once) is placed upon the user. -- Best regards, Andrey Tarasevich |
| "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 16 11:55PM -0800 On 1/16/2022 11:51 PM, Chris M. Thomasson wrote: > Now, it would be funny if a compiler would output something like: > this function cannot be inlined, go ahead and try turning on link time > optimization, and try again? ;^) Then, the programmer turns on link time optimization, and tries again. The compiler says, well, shit happens! No inline for you! Better try asm. |
| Juha Nieminen <nospam@thanks.invalid>: Jan 17 09:50AM > function would have the same effect. To me, at least, the "static > inline" is a documentation of how you see the function and expect it to > be used. The difference between a 'static' (or 'static inline') function and a (non-static) 'inline' function is that in the former case the function gets instantiated as many times as there are compilation units that call it (or in every compilation unit that includes the header, regardless of whether anything calls it or not, as some more primitive C compilers do. Yes, they exist.) In the latter case the function is instantiated in the executable binary only once, just like in C++ (but in C you have to explicitly tell *where* it's instantiated, while in C++ it's automatic.) Since as far as I remember you cannot have 'static' variables inside an 'inline' function (unlike in C++), the only possible situation that I can think of where you have to make an 'inline' function non-static is if the function needs to have a unique pointer (eg. if you for some reason need to compare function pointers). Or if you need to squeeze even the last bits out of the executable binary size and do not want the function to be duplicated. Sometimes you can get away with using (non-static) 'inline' without specifying where the function should be instantiated (if the compiler never generates an actual function call), but I think that's non-standard behavior. |
| David Brown <david.brown@hesbynett.no>: Jan 17 11:35AM +0100 On 17/01/2022 08:51, Chris M. Thomasson wrote: > Now, it would be funny if a compiler would output something like: > this function cannot be inlined, go ahead and try turning on link time > optimization, and try again? ;^) "inline" does not make such demands of the compiler - in C or C++. In C++ it is very useful for letting you put definitions in headers (an "ODR defeater", as some call it). In C, with decent compilers, it is much less useful as you could use a non-inline "static" function in a header and get pretty much the same effect as a "static inline" function. To me, it is as much a documentation of the programmer intention as anything else. If you want to insist that the compiler really does inline a function, you need to use compiler-specific features - like gcc/clang "always_inline" attribute. If you want the compiler to complain when it can't inline a function, gcc has "-Winline" (or "-Werror=inline" for an error). |
| Bonita Montero <Bonita.Montero@gmail.com>: Jan 17 12:40PM +0100 Am 14.01.2022 um 02:51 schrieb Andrey Tarasevich: > code at the call site. The purpose of `inline` keyword is to allow you > to defeat ODR restrictions for a function (or a variable) with external > linkage. ... That's true for inline-variables but for inline-functions only parti- tially. For inline functions inline is also a hint for the compiler to inline the code in the calling code. But this is only a hint and not mandantory. |
| Juha Nieminen <nospam@thanks.invalid>: Jan 17 12:55PM > Some years ago g++ treated `inline` as an almost absolute inlining > directive. Does anyone have a reference or documentation that shows that compilers like gcc, clang, icc and Visual Studio behave differently with respect to inlining a function depending on whether the function has been marked as 'inline' or not? For the longest time I have got the impression that if a compiler sees the function definition from the call location, it uses a heuristic to determine whether it will inline the function or not, and this heuristic completely ignores whether the function has been marked as 'inline'. However, I could well be wrong. Maybe they use different heuristics depending on whether that keyword appears or not? |
| David Brown <david.brown@hesbynett.no>: Jan 17 03:14PM +0100 On 17/01/2022 13:55, Juha Nieminen wrote: > completely ignores whether the function has been marked as 'inline'. > However, I could well be wrong. Maybe they use different heuristics > depending on whether that keyword appears or not? That is correct, as far as I know. There are some flags that can influence inlining, such as whether static functions that are only called once are always inlined or not, but you rarely use them - enable an appropriate level of optimisation (-O2 is good for many uses), and the compiler will probably do a better job than the programmer would at figuring out the best policy for each function. The compiler can also be more flexible (such as partial inlining) than a programmer could specify. If I want control over inlining (which I occasionally do in my embedded development), I use gcc's "always_inline" or "noinline" attributes. If Alf is correct about gcc treating "inline" as "an almost absolute directive", it must have been a /long/ time ago - gcc 2.95 from pre-C99 days did heuristic-based inlining optimisations, and that's as far back as I have bothered checking. |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Jan 17 10:13AM -0800 On 1/17/2022 3:40 AM, Bonita Montero wrote: > tially. For inline functions inline is also a hint for the compiler > to inline the code in the calling code. But this is only a hint and > not mandantory. Um... Once again "only a hint to inline and not mandantory" is completely meaningless wording within the context of a formal document. Such wording should be relegated to a footnote, to explain the etymology of the keyword. Currently, this is essentially a defect in the standard, which only serves to confuse people. The proper wording describing the purpose and intent of `inline` should say something along the lines of "the purpose of `inline` keyword is to make the definition of a function with external linkage visible in all translation units without triggering an ODR violation". Once they've stated that, they can also add a bit of rationale, e.g. "this helps facilitate inlining and many other useful optimizations" Note, BTW, that when a full function body is visible to the compiler, the optimization benefits of such visibility go far beyond inlining. -- Best regards, Andrey Tarasevich |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Jan 17 10:24AM -0800 On 1/17/2022 4:55 AM, Juha Nieminen wrote: > like gcc, clang, icc and Visual Studio behave differently with respect > to inlining a function depending on whether the function has been marked > as 'inline' or not? Depends on the compiler settings. "By default" GCC considers for inlining only those functions that are explicitly declared `inline`. In order to inline something else one'd need to enable `-finline-functions-called-once` (included in `-O1`), `-finline-functions`, `-finline-small-functions` (included in `-O2`) and so on. -- Best regards, Andrey Tarasevich |
| David Brown <david.brown@hesbynett.no>: Jan 17 07:46PM +0100 On 17/01/2022 19:24, Andrey Tarasevich wrote: > `-finline-functions-called-once` (included in `-O1`), > `-finline-functions`, `-finline-small-functions` (included in `-O2`) and > so on. The manual is a bit inconsistent here. Under optimisation options, it says you need "-fno-inline" to turn off inlining of functions declared "inline". Under "An Inline Function is As Fast As a Macro", it says that no functions are inlined if optimisation is not enabled. |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 17 02:39PM -0500 On 1/17/22 4:50 AM, Juha Nieminen wrote: ... > Since as far as I remember you cannot have 'static' variables inside > an 'inline' function (unlike in C++), That only applies to inline functions with external linkage, and only for modifiable objects. The same is true of objects with thread storage duration. Such functions are also prohibited from containing a reference to an identifier with internal linkage. (C standard 6.7.4p3) A key difference between C and C++ that is relevant to this thread is that, in C++, 'inline' is an ignorable hint that inline substitution should be performed. In C, it's an ignorable hint that "that calls to the function be as fast as possible.", with the method where by that might be achieved being unspecified. |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Jan 17 04:15PM -0500 On 1/17/22 1:13 PM, Andrey Tarasevich wrote: ... > completely meaningless wording within the context of a formal document. > Such wording should be relegated to a footnote, to explain the etymology > of the keyword. You might disapprove of such a feature, but being a non-mandatory hint is the primary purpose of this feature. It seems odd to me to mention the primary purpose of a feature only in a footnote. > say something along the lines of "the purpose of `inline` keyword is to > make the definition of a function with external linkage visible in all > translation units without triggering an ODR violation". Could you show me how you would use inline for the purpose of violating the ODR rules, where there's no more appropriate way to achieve the same objective? Allowing you do do so was certainly not the purpose of 'inline'. |
| Tim Rentsch <tr.17687@z991.linuxsc.com>: Jan 17 10:13AM -0800 > So if some problem involving UTF-8 needs only half of error > checking then it is fair to expect it been said in problem > description. Yes, I know you have no shortage of strong opinions. |
| Tim Rentsch <tr.17687@z991.linuxsc.com>: Jan 17 10:28AM -0800 > return len; > } > Has anyone further ideas to improve this ? Just for fun - size_t utf8_units_two( const char *s ){ size_t r = -1; unsigned char c; next: switch( r++, c = *s++, c >> 3 ){ cases(16,17,18,19,20,21,22,23,31): return -1; cases(30): if( c = *s++, c >> 6 != 2 ) return -1; cases(28,29): if( c = *s++, c >> 6 != 2 ) return -1; cases(24,25,26,27): if( c = *s++, c >> 6 != 2 ) return -1; cases(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15): goto next; cases(0): if( c != 0 ) goto next; } return r; } (Note: the cases() macro produces one 'case X:' for each argument X except the last one where the ':' is omitted, written using the standard C preprocessor, and left as an exercise for any ambitious readers.) Incidentally, this code provides the only example I remember where using 'goto' is pretty much unavoidable, in that any re-writing without 'goto' seems awkward or inferior in some other way. I guess I should say, at least not that I could find, maybe someone else can do better. This code also has the interesting property that along the main code path there are no conditional branches (as compiled by gcc under -O2). |
| "Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jan 17 09:51PM +0100 On 17 Jan 2022 19:28, Tim Rentsch wrote: > } > return r; > } That's very ugly. > argument X except the last one where the ':' is omitted, > written using the standard C preprocessor, and left as an > exercise for any ambitious readers.) Exercise for you: test that unrevealed macro with Visual C++. (Making it work also with Visual C++ is doable.) > re-writing without 'goto' seems awkward or inferior in some > other way. I guess I should say, at least not that I could > find, maybe someone else can do better. The `for(;;)`, `continue;` and `break;` constructs come to mind, so you're right, someone else can do better. At a guess the code counts the number of Unicode code points? Does it return -1 also for "too long" UTF-8 sequence? > This code also has the interesting property that along the main > code path there are no conditional branches (as compiled by gcc > under -O2). Smart compiler removed all the `if`'s? I guess you're flame-baiting a little just for fun, but I chose to take it seriously. - Alf |
| You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment