Deutsch English Français Italiano |
<875xsdc2jq.fsf@bsb.me.uk> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Ben Bacarisse <ben@bsb.me.uk> 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, 06 Aug 2024 12:29:29 +0100 Organization: A noiseless patient Spider Lines: 88 Message-ID: <875xsdc2jq.fsf@bsb.me.uk> 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> MIME-Version: 1.0 Content-Type: text/plain Injection-Date: Tue, 06 Aug 2024 13:29:31 +0200 (CEST) Injection-Info: dont-email.me; posting-host="4018bc0269ebd1911c8af6d27249f6bd"; logging-data="1659005"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18AGBMXUsQysbU69zAhKUaUrvlC2dbQXGA=" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:90OFhGaHhipsx7gWrEgvDHFRz40= sha1:JMrRQLX90g3CLGDG271ToDQQQt0= X-BSB-Auth: 1.5df03e7f0fcdebb02925.20240806122929BST.875xsdc2jq.fsf@bsb.me.uk Bytes: 4743 "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. -- Ben.