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

Reply via email to