Deutsch   English   Français   Italiano  
<vu6kkt$392e6$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: bart <bc@freeuk.com>
Newsgroups: comp.lang.c
Subject: Re: Loops (was Re: do { quit; } else { })
Date: Tue, 22 Apr 2025 00:33:48 +0100
Organization: A noiseless patient Spider
Lines: 129
Message-ID: <vu6kkt$392e6$1@dont-email.me>
References: <vspbjh$8dvd$1@dont-email.me> <20250413072027.219@kylheku.com>
 <vtgpce$39229$1@dont-email.me> <vti2ki$g23v$1@dont-email.me>
 <vtin99$vu24$1@dont-email.me> <vtiuf0$18au8$1@dont-email.me>
 <vtj97r$1i3v3$1@dont-email.me> <vtl166$36p6b$1@dont-email.me>
 <vtlcg0$3f46a$2@dont-email.me> <vtnekn$1fogv$1@dont-email.me>
 <vto2mb$20c4n$1@dont-email.me> <vtu4i5$3hteg$1@dont-email.me>
 <vtujko$3uida$1@dont-email.me> <vtvfop$rf2p$1@dont-email.me>
 <vtvto2$15otp$1@dont-email.me> <vu01k7$1bfv2$1@dont-email.me>
 <vu0720$1dva7$1@dont-email.me> <vu2hmg$3jn88$1@dont-email.me>
 <vu2mkc$3noft$1@dont-email.me> <vu38da$735n$1@dont-email.me>
 <vu3j7s$g755$1@dont-email.me> <87ecxmv4t4.fsf@nosuchdomain.example.com>
 <vu401g$reom$1@dont-email.me> <20250420200823.908@kylheku.com>
 <vu5bqp$230jl$2@dont-email.me> <20250421113640.839@kylheku.com>
 <vu67up$2ubvr$1@dont-email.me> <20250421125957.29@kylheku.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 22 Apr 2025 01:33:50 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="d044c27b80dbbae3d03ebae8688adc0f";
	logging-data="3443142"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX1+hognLeicIjKK4er25t7af"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:4qgHsy47xeC36JQ3NzXa3dzyZBs=
In-Reply-To: <20250421125957.29@kylheku.com>
Content-Language: en-GB

On 21/04/2025 21:25, Kaz Kylheku wrote:
> On 2025-04-21, bart <bc@freeuk.com> wrote:
>> On 21/04/2025 19:43, Kaz Kylheku wrote:
>>> On 2025-04-21, bart <bc@freeuk.com> wrote:
>>>> On 21/04/2025 04:16, Kaz Kylheku wrote:
>>>>> - Because they are not gathered in one place, not only is it less>
>>>> readable, but we cannot use while write a macro such as:
>>>>>
>>>>>         for_sqlite_hash (p, &pSchema->trigHash) {
>>>>>           if (some_condition_over(p))
>>>>>             continue; // doesn't stupidly repeat for the same p!
>>>>>         }
>>>>
>>>> I can't write such macros at all. I'm not even sure what this does.
>>>
>>> Have you never worked with a large codebase written by someone other
>>> than you?
>>
>> How large are we talking about?
> 
> Several 100K to millions.

Characters, lines or files of source code, or bytes of binary?

> 
>> I've delved into largish apps in the context of getting my C compiler
>> working. I would describe that experience as 'brutal'.
> 
> Well, that brutal experience is the job of the career software engineer,
> believe it or not. Very few work only on their own original code.
> 
>> If you need to
>> debug someone else's codebase, not to find bugs in that program, but to
>> find why your implementation is failing, then you want as conservative a
>> coding style as possible.
>>
>>
>>> When you open a random file in an unfamiliar code base, pretty
>>> much any function call that is not in the standard library triggers
>>> the "I don't know what this does" response.
>>
>> Yes, a function call. Macros are in an entirely different, evil category.
> 
> No, they aren't. They are just another definition to understand.

I've seen a 33KB C file that expanded to 4MB after preprocessing. Macros 
are evil.

> 
> They can be misused, and also used to make solutions that are more
> complicated than some great ideas that don't involve macros.

You can tell when there is abuse going on, because you find that instead 
of optimising doubling the speed of a program, it will make it 3-4 times 
as fast. Because layers of macros hide the fact that that there are also 
multiple layers of functions which need serious inlining.

> So can anything: an open coded function can be misused to make some
> complicated solution that can be more nicely done with macros.

>> The Lua sources (only a mere 30Kloc), use macros extensively, but also
>> have a habit of giving them ordinary looking names in lower case so that
>> they look like function calls.
> 
> So does ISO C; e.g. assert (expr); offsetof (type, member). So what?

> Macros that provide syntax should blend into the language.

These didn't provide syntax.

Here's a nice example:

         op_arith(L, l_addi, luai_numadd);

Innocent-looking isn't it? It expands to this:

  
{TValue*v1=(&((base+((((int)((((i)>>((((0+7)+8)+1)))&((~((~(Instruction)0)<<(8)))<<(0)))))))))->val);TValue*v2=(&((base+((((int)((((i)>>(((((0+7)+8)+1)+8)))&((~((~(Instruction)0)<<(8)))<<(0)))))))))->val);{StkId 
ra=(base+(((int)((((i)>>((0+7)))&((~((~(Instruction)0)<<(8)))<<(0)))))));if(((((v1))->tt_)==(((3)|((0)<<4))))&&((((v2))->tt_)==(((3)|((0)<<4))))){lua_Integer 
i1=(((v1)->value_).i);lua_Integer 
i2=(((v2)->value_).i);pc++;{TValue*io=((&(ra)->val));((io)->value_).i=(((lua_Integer)(((lua_Unsigned)(i1))+((lua_Unsigned)(i2)))));((io)->tt_=(((3)|((0)<<4))));};}else{lua_Number 
n1;lua_Number 
n2;if((((((v1))->tt_)==(((3)|((1)<<4))))?((n1)=(((v1)->value_).n),1):(((((v1))->tt_)==(((3)|((0)<<4))))?((n1)=((lua_Number)(((((v1)->value_).i)))),1):0))&&(((((v2))->tt_)==(((3)|((1)<<4))))?((n2)=(((v2)->value_).n),1):(((((v2))->tt_)==(((3)|((0)<<4))))?((n2)=((lua_Number)(((((v2)->value_).i)))),1):0))){pc++;{TValue*io=((&(ra)->val));((io)->value_).n=(((n1)+(n2)));((io)->tt_=(((3)|((1)<<4))));};}};};};

 From this, I had to find the bug in my compiler.

(Lua is an interpreter; I write interpreters and they are several times 
faster than Lua for equivalant inputs. I don't need to use such tricks.)

>> Please humour me: What Does It Do?
> 
> It is intended to condense an interation that *you* open-coded, in this
> example upthread:
> 
>         p = sqliteHashFirst(&pSchema->trigHash);
>         while (p != NULL)
>         {
>             sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
>             p = sqliteHashNext(p) )
>         }
> 
> So although I didn't show the definition, I think, of course the intent that it
> does this (i.e. is relevant to the discussion thread) and not something else.
> 
>    for_sqlite_hash (p, hashptr) stmet
> 
> must initialize p using sqliteHashFirst(hashPtr);

This sounds a very specific type of macro, just to replace a simple 
loop. And it is simple; those identifiers make it look scary. This is 
the loop:

      p = a;
      while (p) {
          stmt;
          p = next();            // which turns out to be p = p->next
      }


Given that, do you /really/ need that extra layer of complexity via that 
macro?

> If I had to write 17 loops over SQLite hashes, I'd rather type
> for_sqlite_hash(p, hash)  than
> for (p = sqliteHashFirst(hash); p; p = sqliteHashNext(hash)).

I guess that answers that question! I'd use macros only as a last 
resort; you would use them at the first opportunity.