Deutsch English Français Italiano |
<v8tuls$1q1od$1@dont-email.me> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!feeds.phibee-telecom.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> Newsgroups: comp.lang.c Subject: Re: No warning at implicit removal of const. Was: relearning C: why does an in-place change to a char* segfault? Date: Tue, 6 Aug 2024 12:48:12 -0700 Organization: A noiseless patient Spider Lines: 130 Message-ID: <v8tuls$1q1od$1@dont-email.me> References: <IoGcndcJ1Zm83zb7nZ2dnZfqnPWdnZ2d@brightview.co.uk> <20240801174026.00002cda@yahoo.com> <v8gi7i$29iu1$1@dont-email.me> <slrnvaorkl.34j6.candycanearter07@candydeb.host.invalid> <87zfpvfdk4.fsf@nosuchdomain.example.com> <v8ii17$2q5p1$1@dont-email.me> <87v80ig4vt.fsf@nosuchdomain.example.com> <v8jbvj$2vat1$1@dont-email.me> <87le1ed0dl.fsf@bsb.me.uk> <v8jp3f$321h8$1@dont-email.me> <875xsfdbhf.fsf@bsb.me.uk> <v8pdsn$fgau$1@dont-email.me> <87ttfzb5ar.fsf@bsb.me.uk> <v8rd2g$11vvn$2@dont-email.me> <87frribsgs.fsf@bsb.me.uk> <v8rkb3$156mh$1@dont-email.me> <875xsdc2jq.fsf@bsb.me.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Tue, 06 Aug 2024 21:48:13 +0200 (CEST) Injection-Info: dont-email.me; posting-host="49cc1ebae54dd337cd29762bf6fa6814"; logging-data="1902349"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19MbBU7Nc4AsYQdtew7tneMd585QnRwUIU=" User-Agent: Mozilla Thunderbird Cancel-Lock: sha1:LK+TgWURWKWbER6pEy+hNUyFSmQ= Content-Language: en-US In-Reply-To: <875xsdc2jq.fsf@bsb.me.uk> Bytes: 6297 On 8/6/2024 4:29 AM, Ben Bacarisse wrote: > "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes: > >> I must have completely missed it. Sorry about that. Please redefine? > > It's going to seem silly after all these exchanges. I simply wanted to > know why you chose to use const as you originally posted: > > | struct object_prv_vtable { > | int (*fp_destroy) (void* const); > | int (*fp_read) (void* const, void*, size_t); > | int (*fp_write) (void* const, void const*, size_t); > | }; > > because that looks peculiar (to the point of being arbitrary) to me. > You went on to talk about "self" pointers being const pointers to const > void, but that was not what you wrote, so it did not address what I was > asking about. > > In general, const qualified argument types are rarely used and are even > more rarely used in function (or type) declarations because there have > no effect at all in that position. For example, I can assign fp_destroy > from a function declared without the const-qualified parameter: > > int destroy(void *self) { /* ... */; return 1; } > ... > vtab.fp_destroy = destroy; > > or, if I do want the compiler to check that the function does not alter > its parameter, I can add the const in the function definition (were it > can be useful) even if it is missing from the declaration: > > struct object_prv_vtable { > int (*fp_destroy) (void*); > /* ... */ > }; > > int destroy(void *const self) { /* ... */; return 1; } > ... > vtab.fp_destroy = destroy; > > But if you want the const there so that the declaration matches the > function defintion, why not do that for all the parameters? Basically, > I would have expercted either this (just ine const where it matters): > > struct object_prv_vtable { > int (*fp_destroy) (void *); > int (*fp_read) (void *, void *, size_t); > int (*fp_write) (void *, void const *, size_t); > }; > > and the actual functions that get assigned to these pointers might, if > you want that extra check, have all their parametera marked const. Or, > for consistency, you might have written > > struct object_prv_vtable { > int (*fp_destroy) (void * const); > int (*fp_read) (void * const, void * const, size_t const); > int (*fp_write) (void * const, void const * const, size_t const); > }; > > even if none of the actual functions have const parameters. > > Finally, if you had intended to write what you later went on to talk > about, you would have written either > > struct object_prv_vtable { > int (*fp_destroy) (const void *); > int (*fp_read) (const void *, void *, size_t); > int (*fp_write) (const void *, void const *, size_t); > }; > > or > > struct object_prv_vtable { > int (*fp_destroy) (const void * const); > int (*fp_read) (const void * const, void * const, size_t const); > int (*fp_write) (const void * const, void const * const, size_t const); > }; > > TL;DR: where you put the consts in the original just seemed arbitrary. > > > I'll also note that the term "const pointer" is often used when the > pointer is not const! It most often mean that the pointed-to type is > const qualified. As such, it's best to avoid the term altogether. > I wanted to get across that the pointer value for the first parameter itself should not be modified. I read (void* const) as a const pointer to a "non-const" void. Now a const pointer to a const void is (void const* const), from my code, notice the first parameter? I consider the first parameter to be special in this older OO experiment of mine. It shall not be modified, so I wrote it into the API: struct device_prv_vtable { int (*fp_read) (void* const, void*, size_t); int (*fp_write) (void* const, void const*, size_t); }; // impl... static int usb_drive_device_read(void* const, void*, size_t); static int usb_drive_device_write(void* const, void const*, size_t); int usb_drive_device_read( void* const self_, void* buf, size_t size ) { struct usb_drive* const self = self_; printf("usb_drive_device_read(%p, %p, %lu)\n", (void*)self, buf, (unsigned long)size); return 0; } int usb_drive_device_write( void* const self_, void const* buf, size_t size ) { struct usb_drive* const self = self_; printf("usb_drive_device_write(%p, %p, %lu)\n", (void*)self, buf, (unsigned long)size); return 0; }