On 7/17/2024 6:38 AM, Bart wrote:
On 13/07/2024 10:39, BGB wrote:
But, as I see it, no real point in arguing this stuff (personally, I have better stuff to be doing...).
We all do. But this group seems to be about arguing about pointless stuff and you might come here when you want a respite from proper work.
However (here I assume you've gone back to Quake but that other interested parties might be reading this), consider the program below.
I got back to debugging...
Ironically, one of the big bugs I ended up finding was related to internal struct handling "leaking through" and negatively effecting stuff.
say:
typedef struct foo_s foo_t; // don't care what it contains for now.
foo_t arr[...];
foo_t temp;
int i, j;
...
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
Internally, it would load a reference to arr[i] into temp, but then this location would get overwritten before the third assignment happened, causing the incorrect contents to be copied to arr[j].
For now, have ended up changing stuff such that any struct-assignment (for structs in the "by-ref" category) to a local variable will instead copy the contents to the memory location associated with that struct.
In this case, it causes the 3 needed memory copies rather than 2, which is less efficient in other cases, but there is no obvious way otherwise to tell that the source wont be overwritten before it's value is used.
Granted, in my own code I would have typically used explicit "memcpy()" or similar. But, ironically, had more bugs in the past where:
memcpy(&temp, &arr[i], sizeof(foo_t));
Would assume that (since the source and destination type match), that the copy was also correctly aligned for the type. There were cases where this assumption was breaking as well (my instructions for loading/storing 128-bits at a time are alignment sensitive, unlike those for 64 bits and smaller; so one can't use a 128-bit load/store if the alignment is unknown, and instead need to use pairs of 64-bit operations).
I guess one question might be, if one were designing a new language, how one might best address this stuff. Though, the "easiest" way would be to design structs to have "lazy copy" semantics, and possibly have a special operator for immediate copy.
Say:
temp=arr[i]; //implicit by reference / lazy copy
temp:=arr[i]; //immediate copy
Where lazy-copy is usually the higher performance option, just breaks stuff if the source gets modified or overwritten before the copy happens.
Well, or have the compiler have a mechanism to realize that a latter statement would modify the results of a former statement and then turn the lazy copy into an immediate copy (at present, this would require possibly needing to add some way to distinguish these operations at the IR level).
Well, or another option being to make immediate-copy the default semantics, as in C. And, then possibly overload '&=' or similar to mean "lazy copy" when applied to structs (but... this has its own annoyances).
That sets up an array and then sums its elements by calling 3 different functions to do the job:
(1) Using normal C pass-by-value
(2) Using C pass-by-value to emulate call-by-reference
(3) Using fantasy true call-by-reference as it might appear if C had the
feature
(I'd hoped C++ would run this, but it didn't even like the middle function.)
I'm asking people to compare the first and third functions and their calls, and to see if there's any appreciable difference between them. There will obviously be a difference in how the A parameter is declared.
---------------------------------------------
#include <stdio.h>
typedef int T;
int sum_byvalue(T* A, int n) {
int i, sum=0;
for (i=0; i<n; ++i) sum += A[i];
return sum;
}
int sum_bymanualref(T(*A)[], int n) {
int i, sum=0;
for (i=0; i<n; ++i) sum += (*A)[i];
return sum;
}
int sum_bytrueref(T (&A)[], int n) {
int i, sum=0;
for (i=0; i<n; ++i) sum += A[i];
return sum;
}
int main(void) {
enum {N = 10};
T A[N] = {10,20,30,40,50,60,70,80,90,100};
int total=0;
total += sum_byvalue (A, N);
total += sum_bymanualref (&A, N);
total += sum_bytrueref (A, N);
printf("%d\n", total); // would show 1650
}
---------------------------------------------
Find anything? I thought not.
Those findings might suggest that C doesn't need call-by-reference, not for arrays anyway. Except that at present you can do this:
T x=42;
sum_byvalue(&x, N);
which would not be possible with call-by-reference. Nor with sum_bymanualref, but apparently nobody wants to be doing with all that extra, fiddly syntax. Better to be unsafe!
No real comment here...
My span of "no other work needs to be done IRL, can focus on coding" is starting to fizzle out.
Needing to go do "day job" stuff, and had gotten distracted by small IRL projects, like trying to make a peltier-cooler based cat-food cooler (to try to keep an open can of cat food cool so it doesn't go bad as quickly if left out where the cat can get to it), but now trying to come up with the cheapest/laziest way to current-limit power to the peltier cooloer.
1x peltier cooler, at 12V, tries to pull 6A. This is excessive, and more cooling than I need (it looks like I need ~ 1.5A or 2.0A or so).
I had originally wanted to use multiple coolers in series, but the aluminum plate I used isn't big enough to mount them, but there is still the possible option of multiple peltier coolers under the heat-sink (say, 3 in a row such that there is around 6 ohms of resistance, current at 12V drops to 2A, and is possibly more energy efficient as well).
Have ordered some more, could try putting 4 of them in series for 8 ohms...
Well, the "proper" way to do this would be to have some sort of PWM driver, but...