Hi Greg, I apologize for the slightly misleading example I provided. It was just a simple example name for a function that would let the people viewing it know it doesn't modify anything.
A better example would be something like this: ssize_t mfs_read_page(FAR const struct mfs_sb_s * const sb, FAR char *data, const mfs_t datalen, const off_t page, const mfs_t pgoff) { /* TODO */ return OK; } Best regards, Saurav Pal. On Sun, Jul 14, 2024 at 10:27 PM Saurav Pal <resyfer....@gmail.com> wrote: > Hi all, > > First up, I am extremely sorry for the late response. I traveled the > entire day and finally reached a place with network coverage. > > Thank you, Michal, this clears up my confusion. I was wondering if the > compiler is smart enough for more complex cases. > > And compiler can easily determine if something is const or not without >> the const keyword. > > > Thank you for clarifying the usage of const, Petro, and Nathan. This > clears up the confusion on the suitability of its use. Also thank you, > Petro, for pointing out the C89 compatibility issue in the PR. > > Combining your suggestions, with the problem of bubbling up of the change > if someday a const needs to be removed, as pointed out by Lup. I think it > would be better to keep const (the second const for pointers) for static > functions like Nathan suggests, for maintenance's sake, even though as > Petro points out, this is technically subject to the author's preference. > > Thank you all for providing your help on this matter. > Best regards, > Saurav Pal. > > > On Sun, Jul 14, 2024 at 8:10 PM Nathan Hartman <hartman.nat...@gmail.com> > wrote: > >> That is correct. I was not suggesting to change the interface. We were >> only using read() as an example. >> >> We were basically saying this: >> >> If a function promises not to modify a buffer, its definition should >> contain const like this: >> >> void function_that_does_not_modify_buffer(const uint8_t * buffer); >> >> Internally, the function could modify the buffer *pointer*, but not >> the contents of the buffer itself. For example, it might iterate the >> buffer: >> >> while(*buffer != 0) buffer++; >> >> But it promises not to do this: >> >> *buffer = 0; >> >> And the compiler will enforce that. >> >> But this doesn't make sense: >> >> void function_that_does_not_modify_buffer(const uint8_t * const buffer); >> >> (Added a second 'const' after the '*'.) >> >> This doesn't make sense because we're promising that the function >> won't modify its copy of the pointer, not even to iterate the buffer. >> That's an internal implementation detail that should not become part >> of the function's interface specification. >> >> Cheers, >> Nathan >> >> >> On Sun, Jul 14, 2024 at 12:27 AM Gregory Nutt <spudan...@gmail.com> >> wrote: >> > >> > The prototypes of standard interface functions are specified in the >> > POSIX standard. It would be a POSIX violation to use whatever prototype >> > you happen to like most. No one gets to "improve" POSIX. >> > >> > read() is specified here >> > https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html >> and >> > must *not* include const in the prototype. >> > >> > On 7/13/2024 9:00 PM, Nathan Hartman wrote: >> > > Replying inline below... >> > > >> > > On Sat, Jul 13, 2024 at 3:21 PM Petro Karashchenko < >> > > petro.karashche...@gmail.com> wrote: >> > > >> > >> Hi, >> > >> >> > >> This comes more to the edge of coding language paradigms, personal >> > >> preferences and readability. >> > >> For enable in Rust everything that you define is "const" and if you >> want to >> > >> modify it you should explicitly specify it. On another hand in C >> everything >> > >> you define is modifiable unless you specify "const" to restrict >> unintended >> > >> modification at compile time. This is one of many items that you can >> find >> > >> in discussions why Rust is safer than the C. >> > >> >> > >> The usage of "const" kind of improves compile time checking, but it >> adds >> > >> more text to the lines and makes code harder to read. Like when I >> looked >> > >> into https://github.com/apache/nuttx/pull/12683 I would maybe >> remove most >> > >> of the "const" there in cases like "const mfs_t depth" or "const >> struct >> > >> mfs_ctz_s new_ctz". But again this comes to personal preferences. >> > >> >> > >> Personally I'm trying to balance on the edge and inspire from POSIX >> > >> sometimes. Of course POSIX could define "read" as "ssize_t >> read(const int >> > >> fildes, void * const buf, const size_t nbyte);", but it is defined as >> > >> "ssize_t >> > >> read(int fildes, void *buf, size_t nbyte);" that seems to be more >> readable >> > >> while still sacrifice compile time checking. >> > > >> > > >> > > As I'm thinking more about this, I think it makes sense to define >> read as >> > > ssize_t read(int fildes, void * buf, size_t nbyte) and NOT ssize_t >> > > read(const int fildes, void * const buf, const size_t nbyte) because >> of the >> > > following reason: specifying const in those places affects what the >> > > function implementation can do internally with its stacked copies of >> those >> > > values and address. So if you put those const in the function >> signature, >> > > you would leak an internal implementation detail and you also would >> prevent >> > > alternative implementations that might need to alter those values for >> the >> > > function's use. >> > > >> > > The only time I would suggest to put those 'const' is when the >> function is >> > > static and part of a module's internal implementation, and is NOT >> exported >> > > to the outside world in the form of an API that has to be maintained >> > > forever. >> > > >> > > More below... >> > > >> > > >> > > This also becomes tricky when "const" may be used "when convenient" >> like in >> > >> "jrnl_rdlog" from https://github.com/apache/nuttx/pull/12683. The >> > >> "idx"/"pg" parameters of "jrnl_rdlog" seems also to need "const" like >> > >> "const mfs_t depth" from "jrnl_wrlog", but just because author had a >> > >> preference not to create a temporary variables "mfs_t tmp_pg = >> pg;"/"mfs_t >> > >> tmp_idx = idx;" and it was "more convenient" to use "idx"/"pg" then >> const >> > >> is omitted in that interface. >> > >> >> > >> So summarizing, there is no answer of what is the best or what >> should be >> > >> used. >> > >> >> > >> Note: "const" before or after "*" are ANSI-C compatible, so has >> nothing to >> > >> do with C++ feature enabled in C. Maybe there was something in >> between >> > >> K&R-C and ANSI-C, but that really goes too far back in time. >> > > >> > > >> > > Thinking about how parsing of declarations works in C, it makes sense >> that >> > > const before and after * should have been supported in those early C, >> > > though I don't remember it being explicitly documented in K&R's C >> book. (I >> > > originally learned C from K&R's The C Programming Language book and I >> never >> > > heard of const after * until I learned C++.) >> > > >> > > Cheers >> > > Nathan >> > > >> >