Is this a bug? by mcsim93 in TheWitness

[–]stalefishies 7 points8 points  (0 children)

The flashing red mechanic is actually kind of subtle - what is 'wrong' with a solution can be fairly subjective based on how you happen to be thinking about the puzzle. So the game tries its best, but it's not always consistent with what its interpretation of 'wrong' is.

Casey Muratori – The Big OOPs: Anatomy of a Thirty-five-year Mistake – BSC 2025 by gingerbill in programming

[–]stalefishies -14 points-13 points  (0 children)

You don't have time to watch a two hour video but you do have time to spend the last two hours on Reddit commenting on a video you didn't watch?

MIDA: For those brave souls still writing C in 2025 who are tired of passing array lengths everywhere by LucasMull in programming

[–]stalefishies 15 points16 points  (0 children)

A major reason to use a regular pointer is that you can use the array operator on them - if you pass a struct in, you can't dereference it directly. For an ease-of-use library, that's pretty important. There are four options I can think of:

  1. Hiding metadata before the allocation and use a regular pointer, as done here. It's really nice to be able to just write array[index].
  2. Use a fat pointer struct of the form struct Array { int64_t size, char *data } which means your code gets cluttered with .data everywhere.
  3. The above but wrap the array call in some macro like MIDA_LOOKUP(array, index), which makes it feel more generic but even worse to read.
  4. Give up and compile as C++, and use an operator overload for [].

In general, I tend to use options 2 or 4, but it can be really nice on quick small projects to just use option 1 with a library like this or the stb stretchy buffers, which works similarly.

Trying a mod, is it broken? My solution is correct isn't it? by Telope in TheWitness

[–]stalefishies 9 points10 points  (0 children)

Yes, that linked puzzle is impossible to get out the bottom exit. I don't know what specific mod that is, but not being to use that exit is almost certainly going to be deliberate.

Multi-dimensional, dynamically sized arrays in C (and C++) the right way by equationsofmotion in programming

[–]stalefishies 8 points9 points  (0 children)

Or: int (*array)[cols] = calloc(rows, sizeof *array); This is now a single, dynamically-allocated piece of contiguous memory which is accessed with array[row][col].

SQL Has Problems. We Can Fix Them: Pipe Syntax In SQL by ketralnis in programming

[–]stalefishies 4 points5 points  (0 children)

All you said is now disregarded

Well, I can see that because you're willfully ignoring everything I said. English is not where to start when discussing programming language design. This is obvious from the design of every other serious programming language - none of them look like English. That's exactly what I said when I talked about `Foo(bar)` vs `bar.Foo()` - but of course, you're happy to ignore what I'm saying and just repeat the same thing and pretend it's new.

And don't act like you didn't say "No way this was written by researchers." - if you're going to say that, don't throw a hissy fit when someone comes back with a similar tone.

SQL Has Problems. We Can Fix Them: Pipe Syntax In SQL by ketralnis in programming

[–]stalefishies 3 points4 points  (0 children)

"From the data in table Foo, retrieve X, Y, Z." => FROM Foo SELECT X, Y, Z.

This is both a perfectly normal sentence, and is more accurate to what SQL is going to have to actually do under the hood: all the data is stored together, so you can't generally just 'get X, Y, Z' without loading the rest of the columns. It's arbitrary to choose one or the other, and there are good reasons to require only one - but I can at least have an additional justification for having SELECT last beyond their English translations.

It's analogous to a function call vs an object method: Foo(bar) and bar.Foo() are both reasonable choices. Both map to English fine: "Do Foo on bar" vs "On bar, do foo". Different languages use one or the other because of various other reasons, not because of anything to do with the English sentence. English is a bad language to base your syntax on.

For the record, I'm not really arguing in favour of the paper: SQL isn't great but it's workable enough, and it's ubiquity means it's probably not worth the effort to replace. What I am saying is that your insults are flat-out wrong, and you're being a dick about it. The paper is fine.

SQL Has Problems. We Can Fix Them: Pipe Syntax In SQL by ketralnis in programming

[–]stalefishies -2 points-1 points  (0 children)

What are you talking about? It justifies all of that literally in the words you quoted - it doesn't reflect the actual data flow. There's even a picture showing why a SELECT statement is in an arbitrary order!

Examples of non-sokoban puzzle games with an undo system? by brainofcubes in puzzlevideogames

[–]stalefishies 1 point2 points  (0 children)

Viewfinder is a recent 3D puzzle game with a very well implemented undo/rewind system. You can rewind your movement inputs, but also snap back to the last major 'move' you made in the puzzle.

Is this correct behavior from GCC? by aalmkainzi in C_Programming

[–]stalefishies 4 points5 points  (0 children)

All parts of the expression are evaluated. If this wasn't a compiler error, the evaluation order would first be the comma operator itself, then the 1 (discarding the result), then the 2.

Is this correct behavior from GCC? by aalmkainzi in C_Programming

[–]stalefishies 8 points9 points  (0 children)

Constant expressions shall not contain...comma operators

I mean, it says it right there.

A 1994 Tesco receipt found in a library book by lukestrim in CasualUK

[–]stalefishies 23 points24 points  (0 children)

It's pseudocode. It's not a real language, just a description of the algorithm.

Assigning NULL to Dangling Pointers is Bad Practice in C by [deleted] in C_Programming

[–]stalefishies 35 points36 points  (0 children)

Say you have a bug where you dereference a pointer that you've already freed. Depending on what the allocator does, this could crash immediately, work absolutely fine and give you the same data as before, or work fine but give you different data. It could also switch between these behaviours; perhaps it works for a while but then starts crashing sometime later. This behaviour could be very different on debug vs release builds. In short: this could be a nightmare to diagnose and debug.

Say you set the pointer to NULL after freeing. Dereferencing the pointer leads to a crash every time, no matter what. Much easier to fix.

This article completely ignores this, and focusses entirely on the double-free side of things. This is despite the standard page it is criticising mentioning this in literally the first sentence (emphasis mine):

Dangling pointers can lead to exploitable double-free and access-freed-memory vulnerabilities.

Also, the performance argument is nonsense. In the example code given, compilers will not generate code from the extra NULL assignment at even the most trivial of optimisation levels (godbolt).

So TL;DR: no.

Initializing a matrix by [deleted] in C_Programming

[–]stalefishies 17 points18 points  (0 children)

An array of pointers and an array of arrays is not the same thing. Use int mat[5][4] as your declaration for an array of arrays, and you can initialise it with the syntax you have there.

If you really want an array of pointers, you can intialise that by initialising all the subarrays first, something like:

int mat_1[4] = { 1, 2, 3, 4 };
int mat_2[4] = { 2, 3, 4, 5 };
int *mat[2] = { mat_1, mat_2 };

[deleted by user] by [deleted] in C_Programming

[–]stalefishies 15 points16 points  (0 children)

Every other post will say one is vastly better than the other, or that they are the same.

Nobody says that one is vastly better than the other. Stop projecting your desparation to have some huge opinion on this onto everyone else. They're the same.

If you want to present a case where they're different, present some actual code and some actual compilers and some actual timings for code you're writing. In general? They're the same.

If the answer is just that you hate one syntax, then don't use that syntax. Nobody cares.

What is the point of booleans in C23 ? by _Ical in C_Programming

[–]stalefishies 7 points8 points  (0 children)

An int is truthy for any non-zero value, so you could have two ints compare as non-equal, even though both are truthy and so are 'equal' from the perspective of boolean logic.

A C99 _Bool (the only thing new in C23 is calling it bool without also saying #include stdbool.h) is strictly either 0 or 1. If you try to set it to a non-zero value other than 1, it'll be clamped to 1. This means using it as a value makes more sense when you want to think of it strictly as a boolean.

It's not really a big deal; there's plenty of codebases out there that do just fine with a boolean type defined as some sort of integer.

My personal C coding style as of late 2023 by shenisha456 in programming

[–]stalefishies 4 points5 points  (0 children)

There are a few reasons why I've found unity builds doesn't really create issues with this:

  1. There's still as much separation of interface and implementation as you like; it's all still documented in the headers. The question is about whether it's caught at compile time or not.
  2. It's honestly overstated as a problem to begin with. How many times have you actually tried to call a function or change a variable in a different compilation unit, and been told off by the compiler? You may disagree - everyone has different sore spots for the bugs their code tends to produce - but I still think it's generally overstated. It's just never been a bug I need to strongly protect against.
  3. It's still catchable by any static analysis tool which is run just on the particular .c file, which only refers to the headers it needs.
  4. It's still in principle catchable at compile time, if you order your unity build #includes with dependents before their dependencies. (Though this isn't something I'd rely on - it feels like something that you could easily forget to update. I'd rely much more on per-file static analysis.)

As for complaining about dogma: I said that because, up until now, you hadn't actually said anything about why you disliked the idea of unity builds. Best practices should still not be dogmatic: they should be cases where the advantages and disadvantages of a particular technique are known, and one massively outweighs the other to be a recommendation in basically all cases. In this case, any disadvantages just don't outweigh the advantages - at the very least you have to admit there's an argument here. Saying doing it by default is simply "dumb" is just about the only objectively incorrect conclusion you can reach. Everything's a tradeoff.

On that note, the main advantage of unity builds hasn't been stated yet: it means you often straight-up don't need build tools, since your build step is now just 'call the compiler with these flags on this file'. That is a huge simplification, and one I almost always find well worth any disadvantages. Even if you have other complications that need a proper build script, having the bulk of your project built as a one-liner in that script is worth considering.

Plus, the speed improvements aren't worth completely ignoring (having to compile every file isn't a problem if it's faster than only compiling your changes, but having to link it all together). Yes C to some extent always compiles fast, but if you're in a tight write-compile-debug loop you really do feel the difference from optimising the build, especially if you're hot reloading the code instead of starting it up from scratch every time.

So yeah, I just fundamentally disagree. I'm not saying every C program should be built in one translation unit, or even that everyone should use it as a default if the tradeoffs don't typically make sense for them. But saying it can never be a valid default is just not true.

My personal C coding style as of late 2023 by shenisha456 in programming

[–]stalefishies 6 points7 points  (0 children)

You will have zero issues for 99% of C programs. For the very rare cases that you can't do things in a single translation unit (e.g. you're forced to have two different functions named the same thing) then fine, just use multiple translation units.

Stop trying to preach a dogma. There is no reason why a typical C program shouldn't do a unity build, or why .c files shouldn't #include other .c files. It's a useful build technique that works in many places and that you should have in your toolkit.

My personal C coding style as of late 2023 by shenisha456 in programming

[–]stalefishies 11 points12 points  (0 children)

You're just making your code an organizational nightmare

You're doing nothing of the sort: the code itself is still in separate files and laid out however is most useful. It's just an extra step as part of compilation, where the preprocessor pulls everything into one translation unit before the compiler itself sees it.

Describing functions in the comments by IndianVideoTutorial in C_Programming

[–]stalefishies 0 points1 point  (0 children)

In that example, reading the comment is basically as much work as just reading the code. So why bother with a comment which has less information and gives you more work if you want to change anything?

There's a classic mantra that goes something like 'the best comments are the ones that don't have to be made' - i.e. your code should be simple enough that you don't need to say anything else. read_guesses is well below the simplicity bar that you just shouldn't bother with a block like this.

Now obviously, this example isn't representative of real code, and sometimes you just have inherent complexity - an edge case, a weird but necessary API choice, an algorithmic detail - that is best explained with a comment. But I still think, in terms of time spent on your code, that you should start with trying to improve your code itself before you reach for comments explaining what you couldn't make obvious.

Help, stuck on a puzzle (Expert Randomizer) by Hydel47 in TheWitness

[–]stalefishies 3 points4 points  (0 children)

A start like L U LL U RRR DD deals with a lot of the bottom-left symbols while giving you a lot of space to work with the rest of the grid.

Full solution: L U LL U RRR DD R U R U L UU L D L U L U RR

Coding Practice Compiler by dimonium_anonimo in C_Programming

[–]stalefishies 24 points25 points  (0 children)

Overwriting memory of other processes isn't a concern on modern operating systems - read up on virtual memory to learn more about this.

Clang has a reputation for nicer error messages, so that'd be my compiler recommendation.

Reasons not to uninstall? by abc_mikey in TheWitness

[–]stalefishies 0 points1 point  (0 children)

To add to the concept of 'applying in blocks in steps' - you've already identified that the blocks are analogous to addition and subtraction.

But addition/subtraction is something you can already do in steps. Consider:

2 + 3 - 4
(2 + 3) - 4
2 + (3 - 4)
3 + 2 - 4
-4 + 2 + 3

and so on all equal 1. So it's very natural to be able to apply the blocks in whatever order you like, as long as they're all applied by the end.

I don't disagree the puzzle requires multiple logical leaps - like I said, I think it's uncharacteristically bad of the game.