Programming thread

  • Want to keep track of this thread?
    Accounts can bookmark posts, watch threads for updates, and jump back to where you stopped reading.
    Create account
Such as? C design is perfectly sensible for single-pass compiled procedural language - most of the cases that i have seen people complaining about it is because either they haven't thought about what the alternatives are or because they do not understand with being single-pass entails.
Off the top of my head
strtok, really anything using mbstate_t, is a nightmare
strdup allocating on the heap can cause a lot of fuck ups
Anything in c that has an 'n' variant and is not said variant can go here
FAMs should not exist
Pointer casting between const and non-const has odd implications in many cases
unions having hidden implications for alignment

Idk, it has a lot of warts, and knowing how to avoid them is a big part of the learning curve
 
Practically, the usual shell semantic is the inverse of C: non-zero return values are "errors", functionally akin to "false" in eg. if statements. I think this is my ideal: exactly one truth, many falsehoods. There's a fun hack here for exception handling because your "error return" can just be a pointer to exception information, NULL if error-free.
You need one constant value to represent one of the two, so that the other can be everything else. 0 makes for a very good choice for false in this regard, but I can't think of anything that can adequately represent a singular truth (maybe Ϫ?)
Returning a non-zero value in the event of an error and performing exception handling in the body of an if statement is a common practice in C. An error doesn't mean "false" if you're evaluating whether or not an error occured
 
Off the top of my head
strtok, really anything using mbstate_t, is a nightmare
strdup allocating on the heap can cause a lot of fuck ups
Anything in c that has an 'n' variant and is not said variant can go here
FAMs should not exist
Pointer casting between const and non-const has odd implications in many cases
unions having hidden implications for alignment

Idk, it has a lot of warts, and knowing how to avoid them is a big part of the learning curve
How would you go around getting rid of those complexities? Fixing the issues with strings('n variants fall into this case as well) leads to rust's multum of string types which is nightmare of it's own. FAM and Union alignment issues are inherent to them so idk how you would even go around to simplifying them. As for const and non-const type casting the only way to "fix" it would be to disallow it or go full on rust route.
 
The truth of the matter is (X_n OR X_n-1 OR ... X_1 OR X_0)
This is why I object to the phrase "the truth, the whole truth, and nothing but the truth" in the legal context. If you put a Techpriest like yours truly on the stand, the entire courtroom is going to be filled with parchment chaining things together like true_proposition AND (false_proposition OR (NOT false_proposition)) .... (That is of course where pragmatics steps in.)
Just learn Ada instead of thinking everything that isn't irreparably fucked has to be related to those Rust nitwits.
When will hideous non-passing trooned-out men insist that things like the Boeing 777's fly-by-wire system be migrated from Ada to Rust?
 
Last edited:
#define TRUE in C is an antipattern that breaks logic, eg.

Code:
int a=2;
if(a==TRUE){printf("never reached\n");}

Doesn't stop people from doing it but neither did Rust.
Comparing a boolean variable against a boolean literal (not literally a literal in this case, but effectively one) for equality or inequality is an even bigger antipattern (since the variable is already a boolean that can be used without comparison, either as-is or complemented) so I don't think that's a particularly strong argument.
 
Most of the features he talks about are alright. I don’t even mind the new octal syntax (just that absolutely boneheaded comment). Labeled breaks are, quite frankly, pointless redundancy in a language that has goto. The new if declaration thing is a welcome intrusion of Go into C, although making the conditional expression optional is dumb and works against readability imo. Case ranges are cringe and I will not be using them. C doesn’t have ranges as a first class feature like some languages, and so shoving this syntax in this one very specific situation is inconsistant and ugly. Moderns may not like it, but the proper C way to do this is with case fallthrough and explicitly including each value.

Goto and case fallthrough may draw the ire of modern computer linguists, but they’re integral parts of C and including what are effectively macros on top of them to satiate people who hate them is just silly. Frankly, any imperative language that doesn’t include goto is gimping itself to some degree. There are some situations where it is just the best option.
All this discussion of improving C and changing how switch statements work reminds me of this insanely relevant classic:


Terry said:
Any nigger can make some nigger feature, but I have improved it in a way that is not niggerlicious, ok?

idk how I feel about the newer C changes (ANSI C is the only C for me), but I like the improvement Terry presents here; it helps avoid a lot of unnecessary nesting and inlines.

How would you go around getting rid of those complexities? Fixing the issues with strings('n variants fall into this case as well) leads to rust's multum of string types which is nightmare of it's own. FAM and Union alignment issues are inherent to them so idk how you would even go around to simplifying them. As for const and non-const type casting the only way to "fix" it would be to disallow it or go full on rust route.
The answer of course being abstracting all of that shit away in some form and taking the C out of C. We have enough high-level toy languages.

Edit: extra tangent
(since the variable is already a boolean that can be used without comparison, either as-is or complemented)
The complement is interesting from a design perspective. Arguably, 0 being false is rooted in binary representations of true and false (0 and 1) and how comparisons end up being bitwise operations at a lower level. Like in a lot of other areas of math, this makes 0 (or your null, in a strictly mathematical sense) a sort of immutable anchor point. From this immutable definition of false, we can define true: NOT false.

The bitwise complement is where you start to see how things get fucky when trying to assign a singular value to true. By its very nature, its result is dependent on the size of the value being operated on. While a big chain of 0s clumped together is still treated as 0.
This, in essence, is why I strongly dislike when languages provide truthiness for ints and then hard-code true to be 1 and only 1. It takes away all of the immense mathematical power (heh) 0 gives you.
 
Last edited:
It's telling that most everyone's first exposure to C++ is this alien.
whoever thought it was a good idea to overload the bit shift operator with stream writing?
Aside from the operator horror show (cin bugs me more, but they're both awful), std::endl is objectively a nigger's design. It doesn't just "end" the line like a \n does; it also flushes the buffer. The fact this isn't made to be immediately clear from the name is bonkers to me.
 
Last edited:
Aside from the operator horror show (cin bugs me more, but they're both awful), std::endl is objectively a nigger's design. It doesn't just "end" the line like a \n does; it also flushes the buffer. The fact this isn't made to be immediately clear from the name is bonkers to me.
How the fuck does that even work? Does the buffer recognize that it just received a newline and flush automatically, or does endl include some special extra character that tells the buffer to do that? Or is this some insane niggerlicious voodoo where sending endl secretly calls some method on the stream?
 
How the fuck does that even work? Does the buffer recognize that it just received a newline and flush automatically, or does endl include some special extra character that tells the buffer to do that? Or is this some insane niggerlicious voodoo where sending endl secretly calls some method on the stream?
From cppreference:
Inserts a newline character into the output sequence os and flushes it as if by calling os.put(os.widen('\n')) followed by os.flush().
Needlessly and niggerishly obscuring all of this behind a shittily-named inline.

Extra info about how gay and stereotypically C++ their I/O flushing setup here is:
This manipulator may be used to produce a line of output immediately, e.g. when displaying output from a long-running process, logging activity of multiple threads or logging activity of a program that may crash unexpectedly. An explicit flush of std::cout is also necessary before a call to std::system, if the spawned process performs any screen I/O. In most other usual interactive I/O scenarios, std::endl is redundant when used with std::cout because any input from std::cin, output to std::cerr, or program termination forces a call to std::cout.flush(). Use of std::endl in place of '\n', encouraged by some sources, may significantly degrade output performance.

In many implementations, standard output is line-buffered, and writing '\n' causes a flush anyway, unless std::ios::sync_with_stdio(false) was executed. In those situations, unnecessary endl only degrades the performance of file output, not standard output.
The code samples on this wiki follow Bjarne Stroustrup and The C++ Core Guidelines in flushing the standard output only where necessary.

When an incomplete line of output needs to be flushed, the std::flush manipulator may be used.
When every character of output needs to be flushed, the std::unitbuf manipulator may be used.
Seeing that many (but not all) implementations flush anyway with a \n disgusts me a lot. Either use buffers with an explicit call to flush when appropriate or fuck off.

This shouldn't be so convoluted in the first place. Then again, if that were the case, it would no longer be C++.
 
Last edited:
Or is this some insane niggerlicious voodoo where sending endl secretly calls
It's not a secret, your header file will explicitly tell you that adding << std::endl will result in the calling or inlining of this function:

C++:
{ return flush(__os.put(__os.widen('\n'))); }

or some equivalent, depending on what compiler you have.
 
There was a nigger, who came up with this idea:
C++:
cout << "Hello world" << endl;
Well, that's pretty niggerlicious.
They're going for some kind of ocaml-style operator chaining with this, but it kinda falls flat, as evidenced by std::print
 
Back
Top Bottom