| 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.