HN user

dfawcus

572 karma
Posts0
Comments487
View on HN
No posts found.

Covid affecting my sense of smell had an impact on this.

Apart from not being able to taste coffee, I also could not taste freshly ground black pepper, fresh spicy peppers, nor Tabasco sauce.

I could only feel the effects of the capsaicin at the back of my throat after having swallowed.

The flaw with that article, it being the Beeb showing their bias, is that it mainly applies to the English Home Counties.

So it is a southern English habit, not a British one. The other parts of England are more direct, and will use more obvious phrasing. Similarly the other parts of Britain will be more direct.

I understand it works _if_ you declare p as being volatile, or explicitly tag it as _Atomic.

i.e., either of these forms:

    foo * volatile p;
    foo * _Atomic p;
Or at least it did when I was performing a similar experiment.

A section? All of Northumberland, as Wallsend is in Tyne and Wear.

The task of walking (or measuring) the whole of England's coastline is made a bit more difficult by the existence of various islands classed as part of England.

e.g. Isle of Wight, St. Mary's Island, Coquet Island, Lindisfarne, the other Farne islands, etc.

Is it a pint? 4 months ago

The volume of UK and US fluid ounces being different also doesn't help.

The UK pint is 568ml, apparently a US pint is 473 ml.

Attribute (qualifier), or storage class?

https://www.airs.com/blog/archives/428

The use of 'const' in C is very much a mixed blessing; I certainly have experience of the 'const poisoning' issue. Possibly it would have been better as a storage class.

For bool, yes it was a useful addition. Especially for the cases where old code would have something like:

    #define FLAG_A 1u
    #define FLAG_B 2u
    int has_flag_B (something *some) { return some->field & FLAG_B; }
and that was then combined with logic expecting 'true' to be 1; which could sneak in over time.

I had my first go at using it (Github Copilot) last week, for a simple refactoring task. I'd have to say I reasonably specified it, yet it still managed to to fail to delete a closing brace when it removed the opening block as specified.

That was using the Claude Sonnet 4.5 model, I wonder if using the Opus 4.5 model would have managed to avoid that.

Someone being beaten up on the streets is domestic policing issue.

That the perpetrators may turn out to be foreign agents is neither here nor there, only if they were diplomatic staff would it not be a domestic policing issue. However the UK police have largely withdrawn from certain areas, and this would simply be another symptom.

High Court action suggests there was a civil case pursuing the perpetrators (or their principals), rather than a criminal case. With a properly functioning police system, that should not be necessary.

Kahn is the PCC for London, he sets their priorities.

Lockdown mode allows one to optionally disable 2g, maybe it is also the default there. One can turn 2g back on in said mode if desired.

As to 3g, it is largely switched off here, and I understand most of the rest of the world is also disabling it.

However it does not remove images from messages, it just disables certain automatic helpers - e.g. link previews etc.

One can still send photos, etc without any issue.

An interesting theory, however I rather suspect it is basically because Limbo had a similar concept for pseudo-enums.

I allowed (e.g.) a syntax like:

    M0, M1, M2, M3, M4: con (1<<iota);
That was taken from one of the Limbo papers.

Actually lots is still on C89.

I'm trying to drag one program at $employer up to C99 (plus C11 _Generic), so I can then subsequently drag it to the bits of C23 which GCC 13 supports.

This all takes times, and having to convince colleagues during code reviews.

What C23 has done is authorise some of the extensions which GCC has had for some time as legitimate things (typeof, etc).

However the ability to adopt is also limited by what third party linters in use at $employer may also support.

Nah - more that a lot of commercial code is written in it; and it doesn't make sense to replace (or rewrite) it at this time.

For example, I'm maintaining some 20 year old C code, which the employer adopted around 10 years ago. It will likely stay in use at least until the current product is replaced, whenever that may be.

Well his "Normal Functions" (benchmarks/closures/source/normal_functions.cpp in his repo) looks quite similar to what I had with my GNU nested functions using a stand in "wide pointer", and hence no generated trampoline.

(https://news.ycombinator.com/item?id=46243298)

Which rather suggests to me that such a scheme, but generated by the compiler, should have a similar performance to said "Normal Functions" and hence similar to his preferred lambda form.

Since his benchmark environment is so unwieldy, I may have a go at extracting those two code sets to a standalone environment, and measure them so see...

In 1979 the “standard practice in C of passing a large struct to a function” wasn’t just not standard practice, it didn’t exist!

Yes it did exist. It just wasn't mentioned in the original K&R book.

See this page of a memo from November 78, passing and returning structs was supported. When I learn C on a Unix system, there was a copy of this memo in the printed papers section.

https://www.nokia.com/bell-labs/about/dennis-m-ritchie/cchan...

One quibble I have with the piece is the quotes.

        There is a bark of an Englifh tree, which I have found by experience to be a powerful aftringent, and very efficacious in curing aguifh [agues] and intermitting diforders.


        My curiofity prompted me to look into the difpenfatories and books of botany, and examine what they faid concerning it; but there it exifted only by name. I could not find, that it hath, or ever had, any place in pharmacy, or any fuch qualities, as I fufpected afcribed to it by the botanifts.
If (as it appears) the author was unable to type in a long-S, he could at least have used a normal one, making the text more readable.

i.e. Englifh => English; aftringent => astringent; aguifh => aguish; diforders => disorders; curiofity => curiosity; difpenfatories => dispensatories; faid => said; exifted => existed; fuch => such; fufpected afcribed => suspected ascribed; botanifts => botanists

Partially "slamming" where agents would try to get folks to switch to a different billing provider, and get paid a commission. So some fraudulently "sign up" random addresses they were supposed to visit.

The other case has been miscommunication over phone or email to someone actually requesting to change billing provider. Or error on the part of the potential customer.

I've had a bill from some random billing provider. In my case it is common for folks newly arriving in the block of flats to get the digits of the address transposed. Due to them using the common English convention, whereas the part of Scotland I'm in uses a different convention.

Note - as far as I can see, it has similar behaviour to what you propose with _Wide for a wide pointer. Just that it is existing practice, from 40 years ago.

I believe the High-C compiler with this support is still available, for modern embedded CPUs.

The other example of nested functions which you've not mentioned was in Metaware High C.

There they allowed nested functions, but also what they termed "full function values", being a form of fat pointer. Certainly I came across it in High-C v1.7 in 1990, and the full manual for an earlier version (1.2?) from around '85 can be found on Bitsavers.

It had a syntax like:

    extern void Quick_sort(
      int Lo, int Hi, int Compare(int a, int b)!,
      void Swap(int a,int b)!
    );

    static Sort_private_table() {
      Entry Entries[100];
      int Compare(int a,int b) {
        return Entries[a] < Entries[b];
      }
      void Swap(int a,int b) {
        Entry Temp = Entries[a];
        Entries[a] = Entries[b];
        Entries[b] = Temp;
      }
      ...
      Quick_sort(1,100,Compare,Swap);
    }
The above is an extract from their language reference, which you can find here:

https://archive.org/download/Yoshizuki_UnRenamed_Files__D-V/...

It is possible to transform the pure Rosetta form of GNU nested function similar to the pure C, such that it doesn't need any stack trampoline. I wonder if that would be closer in performance to the pure C form.

(I can't be bothered to run his benchmarks)

    #include <stdio.h>
    typedef struct env_ E;
    typedef struct fat_ptr_ Fp;
    typedef int fn(E*);
    struct fat_ptr_ {
      fn *f;
      E  *e;
    };
    #define INT(body) ({ int lambda(E*){ return body; }; (Fp){lambda,0}; })
    struct env_ {
      int k;
      Fp xl; Fp x2; Fp x3; Fp x4;
    };
    #define FpMk(fn,e) {fn, e}
    #define FpCall(fn) (fn.f(fn.e))
    int main(){
      int a(E env, Fp x5){
        int b(E *ep){
          return a( (E){--(ep->k), FpMk(b, ep), ep->xl, ep->x2, ep->x3}, ep->x4 );
        }
        return env.k<=0 ? FpCall(env.x4) + FpCall(x5) : b(&env);
      }
      printf(" %d\n", a( (E){10, INT(1), INT(-1), INT(-1), INT(1)}, INT(0)) );
    }

Even for 'normal' rebases of a multi-commit series (without named feature branches), I habitually use the --onto form. It is simply easier to conceptualise what is happening if one is explicit about the 3 references.

As such, using it for the situation described in the piece then becomes a trivial matter, especially if one also habitually runs a graph viewer - I generally have one or more instances of gitk running all the time.

yet if one does that, and has suitable warnings turned on, GCC will complain:

    array2.c: In function ‘main’:
    array2.c:25:17: warning: passing argument 1 of ‘arr_fn2’ from incompatible pointer type [-Wincompatible-pointer-types]
       25 |         arr_fn2(array);
          |                 ^~~~~
          |                 |
          |                 char *
    array2.c:13:22: note: expected ‘char (*)[15]’ but argument is of type ‘char *’
       13 | void arr_fn2(Arr_15 *arr) {
          |              ~~~~~~~~^~~

The above was -Wall -Wextra

Or are you just referring to the function where one defines it as apparently 'pass by value'?

depending upon how one has structured the code, a less painful way to write the same is:

    typedef char array[5];

    void do_something(array *a) {
        enum { a_Size = sizeof *a };
        memset(*a, 'x', a_Size);
    }
it rather depends upon how painful it will be to create a bunch of typedefs.

Beyond a certain point, if there are too many arrays of the same size with different purposes, my inclination is to wrap the array in a struct, and pass that around (either by pointer or value depending upon circumstances.)

The existence of the decaying form is if I recall correctly a backward compatibility thing from either B or NB; simply because in one or the other pointers were written in the (current) array syntax form.