• "not-const" qualifier for C

    From Thiago Adams@thiago.adams@gmail.com to comp.lang.c on Wed Apr 24 16:24:52 2024
    From Newsgroup: comp.lang.c

    Motivation sample:

    struct X {
    const char* const type;
    };

    struct X * make_x(){
    struct X * p = malloc(sizeof *p);
    if (p)
    {

    p->type = strdup("X"); // *** error, type is const ***

    if (p->type == NULL)
    {
    free(p);
    p = NULL;
    }
    }
    return p; //ok
    }

    void print(struct X * p){
    prinf("%s", p->type);
    }

    void x_destroy(struct X * p)
    {
    free(p->type); // *** warning const to non-const ***
    }

    Now consider we have the keyword "mutable" that removes const from
    struct members.


    struct X {
    const char* const type;
    };

    struct X * make_x(){
    mutable struct X * p = malloc(sizeof *p);
    if (p)
    {
    p->type = strdup("X"); //OK
    if (p->type == NULL)
    {
    free(p);
    p = NULL;
    }
    }
    return p; //ok
    }

    void print(struct X * p){
    prinf("%s", p->type);
    }

    void x_destroy(mutable struct X * p)
    {
    free(p->type); //no warning
    }




    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.c on Wed Apr 24 23:13:07 2024
    From Newsgroup: comp.lang.c

    On 2024-04-24, Thiago Adams <thiago.adams@gmail.com> wrote:
    Motivation sample:

    struct X {
    const char* const type;
    };

    struct X * make_x(){
    struct X * p = malloc(sizeof *p);
    if (p)
    {

    p->type = strdup("X"); // *** error, type is const ***

    if (p->type == NULL)
    {
    free(p);
    p = NULL;
    }
    }
    return p; //ok
    }

    Different idea: allow all conversions without a cast which only
    add qualifiers anywhere in the type:

    struct X {
    const char* const type;
    };

    struct mutable_X {
    char* type;
    };

    struct X * make_x()
    {
    struct mutable_X * p = malloc(sizeof *p);
    if (p)
    {

    p->type = strdup("X");

    if (p->type == NULL)
    {
    free(p);
    p = NULL;
    }
    }
    return p; // ok: X differs from mutable_X only in having more qualifiers
    }

    Regarding freeing, we fix that with a different freeing interface:

    extern void cvfree(const volatile void *p);

    void x_destroy(struct X * p)
    {
    cvfree(p->type); //no warning: conversion only adds qualifiers
    }

    Freeing is not mutation; it makes sense to free via a qualified
    pointer. Const objects can die, e.g:

    {
    const int x = 42;
    }

    The free function taking a void * is a misfeature in the C library.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Thiago Adams@thiago.adams@gmail.com to comp.lang.c on Wed Apr 24 22:36:07 2024
    From Newsgroup: comp.lang.c



    Em 4/24/2024 8:13 PM, Kaz Kylheku escreveu:
    On 2024-04-24, Thiago Adams <thiago.adams@gmail.com> wrote:
    Motivation sample:

    struct X {
    const char* const type;
    };

    struct X * make_x(){
    struct X * p = malloc(sizeof *p);
    if (p)
    {

    p->type = strdup("X"); // *** error, type is const ***

    if (p->type == NULL)
    {
    free(p);
    p = NULL;
    }
    }
    return p; //ok
    }

    Different idea: allow all conversions without a cast which only
    add qualifiers anywhere in the type:

    struct X {
    const char* const type;
    };

    struct mutable_X {
    char* type;
    };




    In this case the types struct X and struct mutable_X are not
    convertible. They are not the same type.

    I forgot to put a sample but

    void f(struct X x);
    mutable struct X x;
    f(x); //ok from mutable to const is fine




    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Kaz Kylheku@643-408-1753@kylheku.com to comp.lang.c on Thu Apr 25 01:47:45 2024
    From Newsgroup: comp.lang.c

    On 2024-04-25, Thiago Adams <thiago.adams@gmail.com> wrote:


    Em 4/24/2024 8:13 PM, Kaz Kylheku escreveu:
    On 2024-04-24, Thiago Adams <thiago.adams@gmail.com> wrote:
    Motivation sample:

    struct X {
    const char* const type;
    };

    struct X * make_x(){
    struct X * p = malloc(sizeof *p);
    if (p)
    {

    p->type = strdup("X"); // *** error, type is const ***

    if (p->type == NULL)
    {
    free(p);
    p = NULL;
    }
    }
    return p; //ok
    }

    Different idea: allow all conversions without a cast which only
    add qualifiers anywhere in the type:

    struct X {
    const char* const type;
    };

    struct mutable_X {
    char* type;
    };

    In this case the types struct X and struct mutable_X are not
    convertible. They are not the same type.

    And your mutable keyword is a syntax error in the current C language!

    The idea is that we allow "pointer to struct mutable_X" to convert to
    "pointer to struct X" without a cast, because the two types are
    structurally equivalent, and every element of the destination type at
    least as qualified as its counterpart in the source type.

    I don't entirely like the idea because it entails structural
    equivalence. That has various problems. Ideological: we are used
    to "struct foo" and "struct bar" (in the same translation unit)
    being different types. Structural equivalence requires complete
    types. We could end up with the situation where "foo *" cannot
    convert to "bar *" without a cast in one scope in the program
    where foo is an incomplete type, but in another scope, foo is
    completed in a way that the assignment is compatible.
    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Blue-Maned_Hawk@bluemanedhawk@invalid.invalid to comp.lang.c on Thu Apr 25 03:47:19 2024
    From Newsgroup: comp.lang.c

    If you wish to have certain properties of a struct be changeäble only by specific subroutines, not the programmer, then you can use an opaque
    struct.
    --
    Blue-Maned_Hawk│shortens to Hawk│/blu.mɛin.dʰak/│he/him/his/himself/Mr. blue-maned_hawk.srht.site
    You can also reconsider what it is that you're doing.
    --- Synchronet 3.20a-Linux NewsLink 1.114