Re: Bold and italics, semantics and constness (was: [PATCH v2] mctp.7: Add man page for Linux MCTP support)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



[I removed Michael; not to spam him :]

On 11/22/21 14:52, G. Branden Robinson wrote:
> Hi Alex,
> 
> At 2021-11-22T12:50:55+0100, Alejandro Colomar (man-pages) wrote:
> [much snipped]
>> I have had a very bad (and luckily short) experience with
>> Lean/Agile/XP/MVP.
> 
> Well, they're all different things.  Supposedly.  Perhaps not.  :-|

My experience was with Agile/Scrum.  I've read about the others, and
they all seem variants of a similar thing.  I can't talk about the
others so much, since I haven't experienced them, but prefer to live
ignorant.  For agile, I can say that, for how my brain works internally,
it just destroys my performance, and my happiness.  Most job offers I
see today, either say Agile, or say nothing at all; I rarely see any of
the others being mentioned in job descriptions.  If I see agile, I will
very likely discard the offer.

> 
>> If I can help sabotage that, I will happily and intentionally do.
> 
> Hustlers will always be flogging "revolutionary" innovations to
> managers, and managers will always suck them up.  It's not even that
> there are never any worthwhile ideas in these manifestos, it's just that
> you can fit that subset on an index card and the margins in publishing
> index cards isn't high enough to attract anyone's interest.

My opinion is (of course I'm not a manager, and wouldn't like to be):
let the programmers program however they are more comfortable.  Each
brain works in a different manner.  Forcing one way will, at best,
reduce performance.  If anything, a manager should recommend reading
about a methodology (maybe after reading about it, the programmer likes
it), not impose it.  I've been in interviews where I've been asked a lot
about if at my current job they used Agile and how much they implemented
of it, and almost no questions about my programming skills...

> 
>> Are we talking about libc, or C documentation in general?  Because
>> libc doesn't have any 'const' variables at all, at least that I know
>> of.
> 
> I was speaking in general, but the Austin Group is kicking around a
> const struct member for 'tm' right now.[1]
> 
>> So we don't even need to care in the Linux man-pages.  Maybe manual
>> pages for other C libraries can better decide what to do with those.
> 
> I have this sick idea that everything that can be const, should be.
> It's better for both parallelism and, generally, robustness.
> 
>> I think we're talking about 2 different things:
>>
>> - 'const' variables
>> - pointers to 'const'
>>
>> 'const' variables can never be cast away.  It's an error.
> 
> Agreed.
> 
>> $ cat pointer_to_const.c
>> void bar(const int *p)
>> {
>> 	int *q;
>>
>> 	q = (int *)p;
>> 	*q = 3;
>> }
>>
>> This is allowed by the compiler, but it is Undefined Behavior _unless_
>> the variable pointed to by 'p' is really not const.  Casting away
>> const is IMO also braindamaged, so I don't consider it a valid thing.
> 
> I remember having to do this on rare occasions, but don't recollect the
> details.  I'm uncertain whether I was working around a bad design or
> just being a bad programmer.

I also remember doing this.  There's a valid scenario:

Callbacks where the interface is generic (void *).  In that case, you
need to provide a prototype that matches the interface, and even if you
don't modify the input, you need to provide a function that accepts a
non-const, to avoid having to cast the function pointer, which would be
even more dangerous.

Then, when you pass const data through the (void *), since you know it
won't be modified (you wrote the callback), you're safe casting it to
(void *).

I think there's no better way around that than casting to (void *).
However, that's rare enough not to be alarmed.

> 
> There is of course the constant pointer to a constant object.
> 
> const int * const foo;
> 
> ...which, because people insist that type qualifiers must come before
> type names so that declarations read slightly more like English, leads
> them to ugly constructions like
> 
> const int *const foo;

I like it this way.  I may be inconsistent, but I'm used to that way :)
I've read an ad-hoc argument that you can read it right-to-left as:
"foo is a const pointer to an int constant."

To try to justify myself, maybe, my brain considers 'const' to be a more
important piece of information than 'int', which is normally already
obvious by the context.  Since 'const' is closer to the left-side blank
it is more easily parsed by my eyes... just trying to make some sense.

> 
> to remind themselves which way the operator binds...when they _could_
> just write things so that a simpler "noun-adjective" rule leads to a
> correct parse in meatspace.
> 
> int const * const foo;

Yes, every objective argument would recommend this form, but
subjectively, it is ugly to my eyes :p

> 
> Klemens flogs this in _21st Century C_ (O'Reilly).
> 
>> One of the things that I like from C++ is that they correctly
>> implemented const.  Hey, "asd" is 'char *' in C, but of course if you
>> modify it, demons fly out of your nose!
> 
> With -fwritable-strings, they stay inside and poke your sinuses with
> pitchforks...surely an improvement(?).

Sometimes I would just like to see backwards compatibility to be
ignored.  There are things that are just wrong.  If C30 decided to make
const-correctness as it should have been from the beginning, and made
string literals to be (const char *), old programs that would want to
recompile with C30 would need to be fixed, but how much of a problem
would that be?  There's always the option to specify -std=c89 if you
want to avoid fixing some program.

But I also like how slow the C standard advances.  That way they avoid
adding much of the insane stuff that C++ adds.  Even the C standard adds
things that I very much doubt they were ever needed (static for array
parameters?).  So in the end, having so few changes is a good thing.

> 
>> Going back to formatting:
>>
>> Pointers to const are just variables.  Their value is the address of
>> some const, but that's not important.  The important thing is that
>> they are variables, and therefore, you use italics with them.
> 
> Okay, I'm with you so far...
> 
>> So the only thing that IMHO should be bold (apart from constants and
>> macros that expand to constants) should be global 'const' variables:
>>
>> const int FOO = 3;
>>
>> which some people prefer over macros, and which in C++, one could
>> write as:
>>
>> constexpr int FOO = 3;
>>
>> In the case above, I don't see a reason why one would want to
>> differentiate that from say
>>
>> #define FOO  3
> 
> It's a good argument.  The only ones that I can marshal against it are
> that in the first case, 'FOO' is a C object and an lvalue (which is
> almost saying the same thing).  I don't know C++ well enough to address
> the second example, but I'm learning C++98 so that I can deal better
> with the groff code base, which is written "Annotated Reference Manual
> C++", a dialect that is as old as groff itself (1990).

The second one guarantees that FOO evaluates to a constant at
compile-time.  Therefore, you can for example use it to initialize
non-VLA array sizes.

I use C++ as "C with extensions" (not even "C with classes").  I like
some of it's extensions so much that I use them in C:

#if !defined(__cplusplus)
#define auto  __auto_type
#endif

If it confuses someone, I'm sorry :)

> 
>> But in function parameters, 'const' is useless in variables, since
>> they already got a copy, so they won't alter the original.  And in
>> pointers, const applies to the pointee, but the pointer itself is
>> variable, so italics.
> 
> I think of 'const' in function definitions as asserting invariants.
> Consider the following example, where I use two consts that it sounds
> like you would not, to prevent 2 different forms of stupidity.

In the function definiton, it may be useful (but not so much).
In the function prototype, it is useless.

> 
>     void func(int const foo, int const * const bar) {
>     //void func(int const foo, int const * bar) {
>     //void func(int foo, int * bar) {
>         foo = 3;  // prevented by 'int const foo'
>         *bar = 4; // prevented by 'int const * bar'
>         bar++;    // prevented by 'int const * const bar'
>     }

I tend to write functions so short (usually fit a screen; < 24 LOC) that
you can see if you're doing something really stupid.  In something like
glibc's source code, where you see functions with more than 200 LOC,
then const may make sense.

I also very consistently differentiate array syntax from pointer syntax,
so I rarely use ++ to advance pointers.

I'd write:

     void func(int foo, const int *bar, int baz[foo])
     {
	 int i = 0;

         foo = 3;  // I'm editing my own copy. There's not much danger
                   // If I'm really stupid in the implementation,
                   // that has nothing to do with the interface.
         *bar = 4; // prevented by 'const int *bar'
         bar++;    // Having a clear distinction in the prototype
                   // makes this mistake very rare.
         baz[i++] = 5;
     }

In glibc code, for example, they don't use const variables in the
prototypes, but they use them in the definitions.  I'd rather write
shorter functions, and a more readable coding style would also help.

I like to limit prototypes to info that is relevant to the interface,
and I also like the definition to be identical to the prototype.

I limit my usage of const to interfaces, and to achieve
const-correctness.  Avoiding silly mistakes in the implementation of an
algorithm creates too much noise to my taste.

> 
>     int main(int argc, char *argv[]) {
>         int foo = 1;
>         int bar = 2;
>         func(foo, &bar);
>         (void) printf("foo=%d, bar=%d\n", foo, bar);
>     }
> 
> When you're writing a parser (groff has many of them), you pass 'const
> char *' around all the time.  Often these pointers are ones you got back
> from strtok() or similar.  You can pass them to a function to do some
> kind of validity checking--but do you want that pointer advanced through
> the string by the helper function, or not?  If not, then you can make
> the pointer const, and rely on the helper function to make a copy of it
> if necessary.  If you do want it to advance the pointer, for instance if
> it's a function that skips comments and/or white space, then you can
> pass a non-const pointer, and it will give you back a pointer that is
> aimed at the next valid input token.

By returning the pointer?  Or by a pointer-to-pointer?  Otherwise, the
edit is only visible to the copy of the pointer.

Regards,
Alex


-- 
Alejandro Colomar
Linux man-pages comaintainer; https://www.kernel.org/doc/man-pages/
http://www.alejandro-colomar.es/



[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux