- Multi-compare operators - 18 Updates
- Casts - 2 Updates
- The C++ pronunciation dictionary, version 1.0 - 1 Update
- Undefined Behaviour - 3 Updates
- Casts - 1 Update
Bart <bc@freeuk.com>: Sep 21 05:28PM +0100 On 21/09/2018 16:17, Rick C. Hodgin wrote: >> possibly have, other than their favourite language doesn't have such >> constructs? > I can think of three off the top of my head: Objections? > if (xt = yt = treal) ... In C-style that would need to be == not == > if (c in {'A'..'Z', '0'..'9', 'a'..'z'}) ... > And simplified: > if (c in {a_z, 0_9, a_z}) ... (I'm introducing simple forms of Range and Set constructs, from my dynamic language where they are first-class types. (Both originally from Pascal; the Set is a bit-set not the complicated container type you find these days.) But they will not be types of their own. The Set construct is used to build 32-, 64- or 128-bit integer values. That limits it to 128 elements (compared with a billion in the other language), but that is enough to deal with ASCII codes. const alpha = ['A'..'Z', 'a'..'z'] # value is 128-bit int const digits = ['0'..'9'] const ident = alpha ior digits ior ['_'] # ior means "|" if c in alpha ... if n in [1,2,4,8] ... if c not in ident ... The Range construct is used for array bounds, as switch-case ranges (gcc has these as 'A'...'Z'), to build Sets, and for tests like this as I've already shown: if a in 0..255 ... Full treatment of such things I don't think belong in a C-class language but cut-down versions as above I believe are useful, and fairly easy to implement. They directly translate to simple integer and bit wise operations.) -- bart |
jameskuyper@alumni.caltech.edu: Sep 21 09:43AM -0700 On Friday, September 21, 2018 at 10:19:36 AM UTC-4, bitrex wrote: > I've been writing C/C++ off and on since ALL THE WAY BACK in the late > 1990s and I can't say it ever occurred to me to write a test like if ( a > < b < c ) ... Well, of course not - (a < b) < c is a pretty unusual thing to want to calculate. In principle, it could happen, and the amount of C code that has been written is so great that it's almost certainly the case that someone, somewhere, has deliberately written a < b < c, knowing that it would be interpreted as (a < b) < c, because that's what they actually wanted to calculate. But it's certainly extremely rare. > ... I'd probably just write (a < b && b < c) by force of habit. And the fact that you'd want to write that implies that you didn't want to calculate (a < b) < c. My objection to this proposal is not based upon the huge quantities of existing code that would be broken by it - such breakage would be extremely rare. My objection is based upon the fact that it is inconsistent with the design of the rest of the language. a < b is a perfectly good expression in it's own right which returns a value of type int. It's behavior in the proposed a < b < c can NOT be describe in terms of the second '<' operating on the value returned by a < b, which makes it very different from any other type of C expression. The only other expression types that surround an operand with tokens are ?: and various expression types that use [], (), or {} to surround the operand. Since none of the members of those pairs can appear on their own, you never get a case where part of the entire expression looks like an expression in it's own right, but isn't treated as one. There's no possibility, in any of the following expressions, that the part extending from the beginning up to b will be interpretable as an expression in it's own right. The same is true of the part starting at 'b' and extending to the right: a ? b : c a[b] a(b) (a){b, c} (a)b _Generic(a, int:b, float:c) |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Sep 21 12:43PM -0400 On 9/21/2018 12:28 PM, Bart wrote: >>> have, other than their favourite language doesn't have such constructs? >> I can think of three off the top of my head: > Objections? I was being silly. I simply added parenthesis around yours. >> if (xt = yt = treal) ... > In C-style that would need to be == not == I just copied what you wrote. I didn't even pay that much attention to what it was because I was just adding the paren- thesis.. > (I'm introducing simple forms of Range and Set constructs, from my dynamic > language where they are first-class types. (Both originally from Pascal; the > Set is a bit-set not the complicated container type you find these days.) I remember those. I've considered how to implement them in CAlive and came up with [|definition|] casks that allow for [|min|value||], [|max|value||], [|range|min,max||]. > But they will not be types of their own. In CAlive, they are not enforced, but they signal an exception for <|range|func()||> to be added wherever needed on any oper- ation. > if c in alpha ... > if n in [1,2,4,8] ... > if c not in ident ... Interesting. > Full treatment of such things I don't think belong in a C-class language but > cut-down versions as above I believe are useful, and fairly easy to > implement. They directly translate to simple integer and bit wise operations.) I really admire your unique and creative approach toward language extensions. I enjoy reading them in the various posts. -- Rick C. Hodgin |
bitrex <user@example.net>: Sep 21 12:49PM -0400 On 09/21/2018 10:57 AM, Bart wrote: > (What would the alternative to nested for-loops be I wonder? Or switch > statements? Or multi-way comparisons, whatever you mean by that. Are we > still allowed 'if' or is that also bad design? Lots of tasks that require nested loops in C can be accomplished in C++ using the standard algorithms operating on containers, you'd want to use those whenever possible. <http://www.cplusplus.com/reference/algorithm/> > I'd be interested in seeing what your code looks like when most control > flow statement are eliminated. I'd imagine it would have either have a > functional look, or perhaps it's just full of C++-ese.) Writing "C++ese" is what all that stuff is there for! golly! > Here's one actual example of mine (syntax not from C or C++, so "=" > means "=="), which is a 4-way compare: > if hd.hsample[2] = hd.vsample[2] = hd.hsample[3] = hd.vsample[3] ... it's an error-prone statement (all copy-paste statements are.) e.g. if you accidentally write: if hd.hsample[2] = hd.vsample[2] = hd.hsample[3] = hd.hsample[3] can someone not familiar see what's different in 5 seconds? if you don't notice it yourself and the incorrect statement returns a valid result that compiles OK ya ded and then you (or someone!) tear ya hair out for four hours trying to find it. Even "Big name" codebases are filled with bugs like that. |
bitrex <user@example.net>: Sep 21 01:01PM -0400 > the proposed a < b < c can NOT be describe in terms of the second '<' > operating on the value returned by a < b, which makes it very different > from any other type of C expression. The two-way comparison operators return bool in C++, yeah? <https://en.cppreference.com/w/cpp/language/operator_comparison> (looks like this topic was cross-posted so maybe some ambiguity about what lang we're talking about here.) in C++ this works fine: if (a < ( b < c ? b : false)) |
jameskuyper@alumni.caltech.edu: Sep 21 10:25AM -0700 On Friday, September 21, 2018 at 1:01:48 PM UTC-4, bitrex wrote: > On 09/21/2018 12:43 PM, jameskuyper@alumni.caltech.edu wrote: ... > > operating on the value returned by a < b, which makes it very different > > from any other type of C expression. > The two-way comparison operators return bool in C++, yeah? True - but the type of the value it returns isn't relevant to the point I was raising. All that matters is that it does return a value, and that the proposed new meaning for a < b < c cannot be interpreted as the second operator operating on the value returned by the first one. C++ has added a lot of new syntax in the latest release, that I'm not yet familiar with - the rest of my message might have to be re-written to cover C++ as well, but I believe that the basic point I'm trying to make is equally valid for either language. > (looks like this topic was cross-posted so maybe some ambiguity about > what lang we're talking about here.) > in C++ this works fine: if (a < ( b < c ? b : false)) It works, in the sense that it has well-defined behavior so long as a, b, and c have appropriate types. I'm not sure there's any easy way to describe what it does. It's certainly not equivalent to either the current meaning of a < b < c, nor the proposed new meaning for that expression. Why do you bring it up? |
Bart <bc@freeuk.com>: Sep 21 06:25PM +0100 On 21/09/2018 17:49, bitrex wrote: > you accidentally write: > if hd.hsample[2] = hd.vsample[2] = hd.hsample[3] = hd.hsample[3] > can someone not familiar see what's different in 5 seconds? Writing: if hd.hsample[2]=hd.vsample[2] and hd.vsample[2]=hd.hsample[3] and hd.hsample[3]=hd.vsample[3] ... would be even more error-prone! It means writing 6 terms instead of 4. And it is necessary for the terms either side of the 'and's to match, which introduces another source of errors when the same term has to be repeated: if updating one instance, you must update the other too. (Note that your modified version compares the same term with itself, which is the sort of thing a compiler might warn about.) if you don't > that compiles OK ya ded and then you (or someone!) tear ya hair out for > four hours trying to find it. Even "Big name" codebases are filled with > bugs like that. Yes. But as I said, using this construct *reduces* the scope for such errors. -- bart |
Keith Thompson <kst-u@mib.org>: Sep 21 10:46AM -0700 > zero-neg-label, zero-zero-label, zero-pos-label, > pos-neg-label, pos-zero-label, pos-pos-label > (The more things change, the more they stay the same.) C++20 is adding a "three-way comparison operator", <=>, inspired by Perl's "spaceship operator". It compares two values and yields less, equal, or greater (of type std::strong_ordering), with some added complications for floating-point operands. Using it with a switch statement would be similar to what you (sarcastically, I presume) propose. See also https://github.com/Keith-S-Thompson/fizzbuzz-c/blob/master/fizzbuzz093.c -- Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" |
Bart <bc@freeuk.com>: Sep 21 06:54PM +0100 On 21/09/2018 17:43, jameskuyper@alumni.caltech.edu wrote: [I might be killfilled by this poster, but decided to post anyway.] > the proposed a < b < c can NOT be describe in terms of the second '<' > operating on the value returned by a < b, which makes it very different > from any other type of C expression. If the syntax is converted to s-expressions, then: A < B < C using the normal semantics could be expressed like this: (LT (LT A B) C) The outer LT operates on the result of the inner LT as you said. My crude implementation performs a transformation so that you end up with: (AND (LT A B) (LT B C)) Which works fine, except there's a flaw because B occurs twice here, and only once in the original source, which is a no-no. A workaround could create a temporary and copy B into that. But I think this requires a special construct within the language, denoted by this: (CHAINCMP (A LT) (B LT) C) This will always have two or more of those pairs (otherwise it's a regular compare), ending with the single tail expression. Then middle terms only appear once, and it's easy to generate the most suitable code. (That this would be incompatible with how both C and C++ work now is a significant detail that shouldn't be overlooked. Both those languages also have a small problem with the relative precedences of EQ/NE, compared with LT/LE/GE/GT. For this proposal, they would really need to be the same.) -- bart |
bitrex <user@example.net>: Sep 21 03:10PM -0400 On 09/21/2018 01:25 PM, Bart wrote: > if hd.hsample[2]=hd.vsample[2] and hd.vsample[2]=hd.hsample[3] and > hd.hsample[3]=hd.vsample[3] ... > would be even more error-prone! It means writing 6 terms instead of 4. I wouldn't write that either! You would use range-based iterators and the std library functions that operate on the iterators returned by containers like std::equal, std::lexicographical_compare, etc. |
Siri Cruise <chine.bleu@yahoo.com>: Sep 21 12:12PM -0700 In article <lnd0t6agkz.fsf@kst-u.example.com>, Keith Thompson <kst-u@mib.org> wrote: > complications for floating-point operands. Using it with a switch > statement would be similar to what you (sarcastically, I presume) > propose. Doesn't everyone want to program in 1966 Fortran? -- :-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @ 'I desire mercy, not sacrifice.' /|\ An almond doesn't lactate. This post / \ Yet another supercilious snowflake for justice. insults Islam. Mohammed |
bitrex <user@example.net>: Sep 21 03:14PM -0400 On 09/21/2018 01:25 PM, Bart wrote: >> with bugs like that. > Yes. But as I said, using this construct *reduces* the scope for such > errors. in situation where you have say a vector and want to compare elements prefer to use proxy objects like iterators for comparisons and not like my_vector[0], my_vector[1], etc. unless you actually have to destructively alter the contents of the container don't touch 'em directly, don't do nothin' with 'em! |
"Öö Tiib" <ootiib@hot.ee>: Sep 21 12:34PM -0700 On Friday, 21 September 2018 22:12:46 UTC+3, Siri Cruise wrote: > > statement would be similar to what you (sarcastically, I presume) > > propose. > Doesn't everyone want to program in 1966 Fortran? The C++ (like always) actually tries to top up the complications invented in other languages. When the operands of spaceship are floating point types then the "three-way comparison" will evaluate to one of four values of std::partial_ordering. ;) |
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Sep 21 03:53PM -0400 On 9/21/2018 3:12 PM, Siri Cruise wrote: > Doesn't everyone want to program in 1966 Fortran? People often make fun of Fortran, but it's still a first-tier compiler receiving modern optimizations provided for by Intel (along with their C++ compiler). https://software.intel.com/en-us/intel-compilers I regularly hear speakers on compute-related videos report that their scientists say there isn't a better language to express the formulas they use for calculation than in Fortran. I've never used it personally. I play to support it with RDC though at some point. -- Rick C. Hodgin |
Bart <bc@freeuk.com>: Sep 21 09:53PM +0100 On 21/09/2018 20:10, bitrex wrote: > I wouldn't write that either! You would use range-based iterators and > the std library functions that operate on the iterators returned by > containers like std::equal, std::lexicographical_compare, etc. So what would you write? In any syntax. Forget the "hd." parts, you have: int hsample[4]; // sampling rate per component int hsample[4]; When number of components is 3 (eg. RGB), then you want to test that hsample[1], vsample[1], hsample[2], vsample[2] (using 0-based index) all have the same value before proceeding. Is there a simpler and more robust way than using (in C syntax and with chained compare ops): if (hsample[1] == vsample[1] == hsample[2] == vsample[2]) ? -- bart |
bitrex <user@example.net>: Sep 21 04:58PM -0400 On 09/21/2018 04:53 PM, Bart wrote: > Forget the "hd." parts, you have: > int hsample[4]; // sampling rate per component > int hsample[4]; ?????? see what I mean I don't trust me either! |
Bart <bc@freeuk.com>: Sep 21 10:28PM +0100 On 21/09/2018 21:58, bitrex wrote: >> int hsample[4]; // sampling rate per component >> int hsample[4]; > ?????? see what I mean I don't trust me either! This is a typo that would be picked up, so is of no consequence. (Obviously one of those will be vsample.) >> Is there a simpler and more robust way than using (in C syntax and >> with chained compare ops): >> if (hsample[1] == vsample[1] == hsample[2] == vsample[2]) I'm still interested in the magical solution that is simple and less error-prone than this. -- bart |
"Öö Tiib" <ootiib@hot.ee>: Sep 21 03:00PM -0700 On Saturday, 22 September 2018 00:28:53 UTC+3, Bart wrote: > >> if (hsample[1] == vsample[1] == hsample[2] == vsample[2]) > I'm still interested in the magical solution that is simple and less > error-prone than this. No need to make new programming languages for that, just write two one-liners in C++11 and done. Nothing magical. Example that will work with operands of any types between what operator == that returns bool exists. template<typename T, typename U> bool allEqual(T&& t, U&& u) { return (t == u); } template<typename T, typename U, typename... Ts> bool allEqual(T&& t, U&& u, Ts&&... args) { return (t == u) && allEqual(u, std::forward<Ts>(args)...); } // done, now you have allEqual(a,b,c,d,...) // usage: #include <iostream> int main() { int hsample[4] = {42, 42, 42, 42}; int vsample[4] = {0, 42, 42, 666}; if (allEqual(hsample[1], vsample[1], hsample[2], vsample[2])) { std::cout << "yes\n"; } } |
Paavo Helde <myfirstname@osa.pri.ee>: Sep 21 07:08PM +0300 On 21.09.2018 18:26, Stefan Ram wrote: > sentence of this post: > reinterpret_cast< ::std::uintptr_t >pointer > static_cast< ::std::uintptr_t >pointer As the second one does not compile, the choice seems easy to me ;-) It does not compile because despite its name uintptr_t is not a pointer type. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Sep 21 09:43PM +0200 On 21.09.2018 17:26, Stefan Ram wrote: > [snip] > reinterpret_cast< ::std::uintptr_t >pointer > static_cast< ::std::uintptr_t >pointer Both are syntax errors. When that's fixed the `static_cast` is invalid. * * * There was once an issue with the standard's wording for `reinterpret_cast`, so that Andrei and Herb recommended static_cast<Ptr_to_A>( static_cast<void*>( ptr_to_B ) ) instead of reinterpret_cast<Ptr_to_A>( ptr_to_B ) ) However, as I recall, but this is a vague memory, the wording was fixed in C++11 so that now the two are also formally equivalent, so no longer is there even a formal reason to use the more convoluted construct. Cheers! - Alf |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Sep 21 04:26PM On Thu, 2018-09-20, Bart wrote: >> Python is different because there's a word "pyton" for the snakes, and >> because Monty Python got local pronounciation back in the 70s. > That doesn't stop Americans pronouncing it as PyTHON. Note that I never said it should. (In fact, I said the opposite.) As far as I'm concerned, this thread is only for entertainment purposes. /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Sep 21 02:33AM +0200 On 21.09.2018 01:48, Tim Rentsch wrote: > This assertion is fairly common, but it isn't right. Running out > of stack space is not undefined behavior as the C standard defines > the term. A lot of people find this very counter-intuitive; That's because it's the wrong standard. For C++ it's the C++ standard that rules. Except where it defers to the C standard. > whether those conditions exist (in the physical machine) or not. > Hence we know what the abstract machine is supposed to do, and > therefore the behavior is defined. Nope. You're confusing the C formal term with the formal term in the C++ standard, which does correspond closely to the common speech meaning. C++17 $3.27 [defns.undefined] <quote> undefined behavior behavior for which this International Standard imposes no requirements [Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. Evaluation of a constant expression never exhibits behavior explicitly specified as undefined (8.20). —end note ] </quote> The note in the brackets is non-normative text, but explains things. In contrast to C++, the C11 definition limits C "undefined behavior" to "behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements", which is indeed counter-intuitive and more than a little bit impractical. > then the program has no undefined behavior as the > Standard uses the term, and running out of stack space > doesn't change that. Point 3 here blatantly contradicts the above quoted definition of "undefined behavior" in C++17, which is the same definition as in earlier C++ standards, back to C++98. > with the C++ standard, so please take that into account. I would > appreciate any pointers for passages in the C++ standard that > might be at odds with what is written above.) Oh. Well. When you try to argue against someone's C++ terminology by referring to a standard for /another language/, you're just too far out. Not that it isn't interesting. I think that the silly definitions the standardization committees sometimes end up with is interesting from a psychological point of view. I think it's about establishing a kind of group speech, using special meanings only known to (psychology term) in-group members, thus helping to identify and exclude others. Cheers!, - Alf |
"Öö Tiib" <ootiib@hot.ee>: Sep 20 06:13PM -0700 On Friday, 21 September 2018 02:49:16 UTC+3, Tim Rentsch wrote: > question, but it is also a meaningless question. The Standard > specifies the behavior of /programs/; it does not specify the > behavior of /situations/. Standard does describe situations. Those are situations that cause malloc to return null pointer or errno to be set ENOMEM or ENOSPC and the like. What else these are? > then the program has no undefined behavior as the > Standard uses the term, and running out of stack space > doesn't change that. Anything that is not defined by any passage of standard *is* undefined behavior in C++. That may be different in C. Is it in C that because standard does not state that automatic storage has limits and what happens when the limits are exhausted then the automatic storage is unlimited in C? > limits of physical hardware are exceeded or not/. Such things > do not exist in the abstract machine, and so the given semantic > descriptions continue to apply. In C++ it is that since standard does not define what happens when some local variable breaks automatic storage limits then what actually happens is undefined behavior exactly because standard did not define it. |
Paavo Helde <myfirstname@osa.pri.ee>: Sep 21 06:52PM +0300 On 21.09.2018 2:48, Tim Rentsch wrote: >> [..scenarios that might overflow the program stack..] > A common reaction at this point might ask "if the behavior is > defined, then where is it defined?" For stack overflow, the behavior might be defined by the implementation. For example, with MSVC++ on x86 there is a way to make stack overflow a recoverable error, though it's tricky to get right and has a good chance to make the whole program slower. Those not faint in the heart should start with the _resetstkoflw() documentation. Note that if the behavior were defined by the C++ standard, MSVC++ could not implement their own behavior (at least not legally). |
ram@zedat.fu-berlin.de (Stefan Ram): Sep 21 03:26PM I wonder whether there is any difference (in value/behavior) between the following two expressions, and which one should be used to convert a pointer to an unsigned integer type in the sense of N2176 (C, not C++!), 7.20.1.4p1 |The following type designates an unsigned integer type with |the property that any valid pointer to void can be converted |to this type, then converted back to pointer to void, and the |result will compare equal to the original pointer: | |uintptr_t . Here are the two expressions referred to by the first sentence of this post: reinterpret_cast< ::std::uintptr_t >pointer static_cast< ::std::uintptr_t >pointer . |
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