• Re: 80386 C compiler

    From Bart@21:1/5 to fir on Sun Nov 24 18:00:29 2024
    On 24/11/2024 17:51, fir wrote:
    Paul Edwards pisze:
    Hi.

    I have been after a public domain C compiler for decades.
    None of them reach C90 compliance. SubC comes the
    closest but was written without full use of C90, which
    makes it difficult to read. I'm after C90 written in C90.

    A number of people have tried, but they always seem
    to fall short. One of those attempts is pdcc. The
    preprocessor was done, but the attempt (by someone
    else) to add C code generation was abandoned.

    I decided to take a look at it, and it looks to me like
    a significant amount of work has already been done.

    Also, my scope is limited - I am only after enough
    functionality to get my 80386 OS (PDOS) compiled,
    and I don't mind short=int=long = 32 bits, I don't
    mind not having float. I don't use bitfields.

    Anyway, I have had some success in making enhancements
    to it, and here is one:

    https://sourceforge.net/p/pdos/gitcode/ci/3356e623785e2c2e16c28c5bf8737e72df >> d39e04/

    But I don't really know what I'm doing (I do know some
    of the theory - but this is a particular design).

    E.g. now that I have managed to get a variable passed to
    a function, I now want the address of that variable passed
    to the function - ie I want to do &x instead of x - and I am
    not sure whether to create a new ADDRESS type, or
    whether it is part of VARREF or what - in the original
    (incomplete) concept. Or CC_EXPR_AMPERSAND.

    I am happy to do the actual coding work - I'm just looking
    for some nudges in the right direction if anyone can assist.

    Thanks. Paul.


    you mean there is no such a compiler? rise a fund for some to
    write it and they will write it..and if few thousand of people
    will give some money there it will be written

    There are any number of open source C compilers. But they need to be
    good enough (too many support only a subset, which may not be enough for
    the OP) and they need to be public domain for the OP's purposes.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Janis Papanagnou@21:1/5 to Paul Edwards on Sun Nov 24 19:52:55 2024
    On 24.11.2024 15:00, Paul Edwards wrote:

    I have been after a public domain C compiler for decades.
    [...] I'm after C90 written in C90.

    Why formulate the latter condition if you can bootstrap?
    (Did you mean; written in a "C" not more recent than C90?)

    Janis

    https://en.wikipedia.org/wiki/Bootstrapping_(compilers)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Paul Edwards on Mon Nov 25 18:23:58 2024
    On 2024-11-24, Paul Edwards <mutazilah@gmail.com> wrote:
    "Janis Papanagnou" <janis_papanagnou+ng@hotmail.com> wrote in message news:vhvsm9$2bmq9$1@dont-email.me...
    On 24.11.2024 15:00, Paul Edwards wrote:

    I have been after a public domain C compiler for decades.
    [...] I'm after C90 written in C90.

    Why formulate the latter condition if you can bootstrap?
    (Did you mean; written in a "C" not more recent than C90?)

    Yes - written in C90 so that it can be maintained with
    just knowledge of C90.

    And also written in C90 so that it is written naturally
    for a C90 programmer, not using a subset of C90

    But, do yourself a favor and, have it as an extension to allow
    non-constant expressions to allow block scoped aggregates:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    (You don't have to use it in the source code of the thing,
    so it can be boostrapped by other C90 compilers without
    the extension.)

    Also, pin down the truncation behavior of / and % to match C99.
    (Though, again, without relying on that in the C90 source
    of the compiler.)

    Define the behavior of a [0] array at the end of a struct,
    so that the C90 struct hack is "blessed" in your implementation.
    The C99 flexible array member cannot be used, after all.
    You can have it so that [0] has the same semantics as C99 []
    in that role.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rosario19@21:1/5 to Kaz Kylheku on Mon Nov 25 22:14:06 2024
    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    void fn(int a)
    {
    int x[3];
    x[0]=foo(); x[1]=bar(); x[2]=a;

    this would be ok with every C compiler

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Ros@invalid.invalid on Tue Nov 26 17:59:08 2024
    On 2024-11-25, Rosario19 <Ros@invalid.invalid> wrote:
    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    No, you cannot rely on that. Maybe it's fixed in a more recent standard,
    but C99 (which I happen to have open in a PDF reader tab) stated that
    "The order in which any side effects occur among the initialization list expressions is unspecified.". This implies that there is no sequence
    point between any two initializing expressions, which means we don't
    know whose expression's function call takes place first.

    In any case, a C90 compiler with the above support as an extension to
    C90 can specify rigid sequencing behavior.

    void fn(int a)
    {
    int x[3];
    x[0]=foo(); x[1]=bar(); x[2]=a;

    this would be ok with every C compiler

    One problem is, if you're doing this because your compiler is C90, you
    also have to do something about all declarations which follow the int
    x[3], since they cannot occur after a statement. You can add another
    level of block nesting for them, or whatever.

    Initialization is preferable to leaving an object uninitialized and
    assigning. There is a scope where the name is visible, but the object
    is not initialized, inviting code to be inserted there which tries
    to use it.

    If I needed foo to be called before bar, I would still rather do
    the following than assignment:

    int f = foo();
    int b = bar();
    int x[3] = { f, b, a };

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kaz Kylheku on Wed Nov 27 11:00:42 2024
    On 26/11/2024 18:59, Kaz Kylheku wrote:
    On 2024-11-25, Rosario19 <Ros@invalid.invalid> wrote:
    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    No, you cannot rely on that. Maybe it's fixed in a more recent standard,

    The implication of the word "fixed" is that you think the current
    standards as somehow "broken" in this respect. Do you think that is the
    case?

    The C standards go to quite an effort to say when you have a guarantee
    about the order of execution, and when the compiler has the freedom to re-arrange things for greater efficiency (and perhaps to discourage
    people from writing unclear code).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Kaz Kylheku on Wed Nov 27 14:59:08 2024
    On 11/27/24 14:42, Kaz Kylheku wrote:
    ...
    The specification has an inconsistency, because it gives the order
    in which initializations occur, yet not the order of evaluation of
    the expressions that produce their values.

    That's not an inconsistency, it's a deliberate choice to give
    implementations freedom to use whichever order is most convenient.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to David Brown on Wed Nov 27 19:42:50 2024
    On 2024-11-27, David Brown <david.brown@hesbynett.no> wrote:
    On 26/11/2024 18:59, Kaz Kylheku wrote:
    On 2024-11-25, Rosario19 <Ros@invalid.invalid> wrote:
    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    No, you cannot rely on that. Maybe it's fixed in a more recent standard,

    The implication of the word "fixed" is that you think the current
    standards as somehow "broken" in this respect. Do you think that is the case?

    The specification has an inconsistency, because it gives the order
    in which initializations occur, yet not the order of evaluation of
    the expressions that produce their values.

    Above we know that x[0] is initialized first before x[1].

    That doesn't even matter unless initializations are being observed,
    which they can be if there is self-reference going on, like:

    int x[3] = { foo(), x[0] + bar(), x[0] + x[1] }

    I'm assuming this sort of thing must to be the purpose for specifying
    the order of initialization.

    It looks inconsistent to me that the effects of the subobjects receiving
    their inital values are ordered, but all other effects are not.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to James Kuyper on Wed Nov 27 21:52:10 2024
    On 2024-11-27, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 11/27/24 14:42, Kaz Kylheku wrote:
    ...
    The specification has an inconsistency, because it gives the order
    in which initializations occur, yet not the order of evaluation of
    the expressions that produce their values.

    That's not an inconsistency, it's a deliberate choice to give
    implementations freedom to use whichever order is most convenient.

    Implementations are not given freedom about initialization order;
    in { A, B } the initialization implied by A happens before B.

    Granting a freedom here while taking it away there is inconsistent.

    Expression B may rely on the initialization A having completed, but
    not on the effects of A having been settled.

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Kaz Kylheku on Wed Nov 27 18:07:04 2024
    On 11/27/24 16:52, Kaz Kylheku wrote:
    On 2024-11-27, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 11/27/24 14:42, Kaz Kylheku wrote:
    ...
    The specification has an inconsistency, because it gives the order
    in which initializations occur, yet not the order of evaluation of
    the expressions that produce their values.

    That's not an inconsistency, it's a deliberate choice to give
    implementations freedom to use whichever order is most convenient.

    Implementations are not given freedom about initialization order;
    in { A, B } the initialization implied by A happens before B.

    Granting a freedom here while taking it away there is inconsistent.

    Expression B may rely on the initialization A having completed, but
    not on the effects of A having been settled.

    I'm sorry - I thought you meant that they were logically inconsistent.
    What you're actually saying is more like stylistically inconsistent.

    In C90, the order in which the initializers were evaluated didn't
    matter, because they were required to be static initializers. It was
    only in C99 that they were allowed to be arbitrary expressions.

    However, in the same version of the standard, designated initializers
    were added. Designated initializers are allowed to update elements in a different order from their order in memory, and to initialize the same
    element multiple times, with only the final initialization actually
    occurring. This can be convenient for setting up a rule and then adding exceptions to that rule. If there weren't a rule mandating the order in
    which initializers were applied, when two or more initializers affect
    the same object, it wouldn't be possible to be certain which one
    overrode the others.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Wed Nov 27 16:45:17 2024
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:

    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    On 2024-11-25, Rosario19 <Ros@invalid.invalid> wrote:

    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    No, you cannot rely on that. Maybe it's fixed in a more recent standard,
    but C99 (which I happen to have open in a PDF reader tab) stated that
    "The order in which any side effects occur among the initialization list
    expressions is unspecified.". This implies that there is no sequence
    point between any two initializing expressions, which means we don't
    know whose expression's function call takes place first.

    N3096 (C23 draft) has :
    """
    The evaluations of the initialization list expressions are
    indeterminately sequenced with respect to one another and thus the order
    in which any side effects occur is unspecified.
    """

    C23 is more explicit (redundant?) than C99, which doesn't mention the
    lack of a sequence point. (C11 dropped sequence points, replacing them
    with "sequenced before", "sequenced after", and "unsequenced", basically
    a new way of describing the same semantics.)

    Given:

    int n = 42;
    int a[] = { n++, n++ };

    C99 could imply that the value of a is merely unspecified, either {
    42, 43 } or { 43, 42 }. Though it can almost certainly be inferred
    from other parts of the C99 standard that there is no sequence
    point between the two evaluations of n++ (I haven't taken the time
    to check).

    Under C99 rules, I believe this initializer has undefined
    behavior, because of more than one modification of an object
    without an intervening sequence point.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Kaz Kylheku on Wed Nov 27 19:26:21 2024
    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    On 2024-11-25, Rosario19 <Ros@invalid.invalid> wrote:

    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    No, you cannot rely on that. Maybe it's fixed in a more recent
    standard, but C99 (which I happen to have open in a PDF reader
    tab) stated that "The order in which any side effects occur among
    the initialization list expressions is unspecified.". This
    implies that there is no sequence point between any two
    initializing expressions, which means we don't know whose
    expression's function call takes place first.

    Challenge exercise for C standard enthusiasts: It is possible
    (in C99 and later) to write an initializer for x[] that puts
    in the same values as the initializer above, but guarantees
    foo() is called before bar(). Hint: nothing else is needed
    besides a different writing of the initializer for x[] (still
    an array of length 3). How to do it?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Kaz Kylheku on Thu Nov 28 09:12:40 2024
    On 27/11/2024 20:42, Kaz Kylheku wrote:
    On 2024-11-27, David Brown <david.brown@hesbynett.no> wrote:
    On 26/11/2024 18:59, Kaz Kylheku wrote:
    On 2024-11-25, Rosario19 <Ros@invalid.invalid> wrote:
    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    No, you cannot rely on that. Maybe it's fixed in a more recent standard,

    The implication of the word "fixed" is that you think the current
    standards as somehow "broken" in this respect. Do you think that is the
    case?

    The specification has an inconsistency, because it gives the order
    in which initializations occur, yet not the order of evaluation of
    the expressions that produce their values.

    Above we know that x[0] is initialized first before x[1].

    That doesn't even matter unless initializations are being observed,
    which they can be if there is self-reference going on, like:

    int x[3] = { foo(), x[0] + bar(), x[0] + x[1] }

    I'm assuming this sort of thing must to be the purpose for specifying
    the order of initialization.

    It looks inconsistent to me that the effects of the subobjects receiving their inital values are ordered, but all other effects are not.


    I don't see any justification in the standard for assuming that the initialisers are evaluated in any particular order. The standard (at
    least my reading of section 6.7.9) gives a clear order to the
    initialisation itself (which may, of course, be re-ordered by the
    compiler under "as-if" rules) so that if you are using designated
    initialisers, it is clear that the last initialiser for each element is
    what counts. Not only does that section say nothing about the order of evaluation for the parts, it says that if an initialiser is overridden,
    then it may not be evaluated at all (with the implication being that it
    might be evaluated and the result dropped).

    Section 6.7.9p23:

    """
    The evaluations of the initialization list expressions are
    indeterminately sequenced with respect to one another and thus the order
    in which any side effects occur is unspecified. 152)

    152) In particular, the evaluation order need not be the same as the
    order of subobject initialization.
    """


    This is very much like the evaluation of arguments to a function call -
    there is no specified order or sequencing between the evaluations of the arguments.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to James Kuyper on Sat Nov 30 01:30:15 2024
    On 2024-11-27, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 11/27/24 16:52, Kaz Kylheku wrote:
    On 2024-11-27, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    On 11/27/24 14:42, Kaz Kylheku wrote:
    ...
    The specification has an inconsistency, because it gives the order
    in which initializations occur, yet not the order of evaluation of
    the expressions that produce their values.

    That's not an inconsistency, it's a deliberate choice to give
    implementations freedom to use whichever order is most convenient.

    Implementations are not given freedom about initialization order;
    in { A, B } the initialization implied by A happens before B.

    Granting a freedom here while taking it away there is inconsistent.

    Expression B may rely on the initialization A having completed, but
    not on the effects of A having been settled.

    I'm sorry - I thought you meant that they were logically inconsistent.
    What you're actually saying is more like stylistically inconsistent.

    In C90, the order in which the initializers were evaluated didn't
    matter, because they were required to be static initializers. It was
    only in C99 that they were allowed to be arbitrary expressions.

    However, in the same version of the standard, designated initializers
    were added. Designated initializers are allowed to update elements in a different order from their order in memory, and to initialize the same element multiple times, with only the final initialization actually occurring. This can be convenient for setting up a rule and then adding exceptions to that rule.

    But it simply ends up being left to right.

    Given { A, B, C }, the members are initialized in order of increasing
    offset address, corresponding to left-to-right order in the syntax.

    Given { [2] = A, [1] = B, [0] = C }, they are initialized in the
    left-to-right order in the syntax: [2] first, then [1] then [0].

    So we have order. And yet we don't have order; the expressions are not
    actually sequenced.

    If there weren't a rule mandating the order in
    which initializers were applied, when two or more initializers affect
    the same object, it wouldn't be possible to be certain which one
    overrode the others.

    It would make sense for that simply to be a constraint violation;
    two initializations for the same object are being requested.

    There is no sequencing in the initialization: { i++, i++ } would
    be undefined behavior. Yet, you can request multiple initializations
    of the same subobject and have it safely resolved to the rightmost?

    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Kaz Kylheku on Fri Nov 29 21:00:20 2024
    Kaz Kylheku <643-408-1753@kylheku.com> writes:

    On 2024-11-27, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:

    If there weren't a rule mandating the order in which initializers
    were applied, when two or more initializers affect the same
    object, it wouldn't be possible to be certain which one overrode
    the others.

    That's wrong. The priority rule for initializing the same subobject
    depends not on order of evaluation but on syntactic order. There
    doesn't have to be a rule for evaluation order to make the order
    of subobject overriding be well defined.

    It would make sense for that simply to be a constraint violation;
    two initializations for the same object are being requested.

    It isn't that simple. There are situations where overriding the
    initialization of a particular subobject makes sense, and is
    useful. Example:

    typedef struct { int x, y; } Bas;
    typedef struct { Bas b[2]; } Foo;

    Foo
    sample_foo( Bas b ){
    Foo foo = { b, b, .b[1].y = -1 };
    return foo;
    }

    The subobject .b[1].y is overridden, but we can't take the previous initialization of .b[1] without changing the semantics.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to Kaz Kylheku on Sat Nov 30 09:00:32 2024
    On 11/29/24 20:30, Kaz Kylheku wrote:
    On 2024-11-27, James Kuyper <jameskuyper@alumni.caltech.edu> wrote:
    ...
    In C90, the order in which the initializers were evaluated didn't
    matter, because they were required to be static initializers. It was
    only in C99 that they were allowed to be arbitrary expressions.

    However, in the same version of the standard, designated initializers
    were added. Designated initializers are allowed to update elements in a
    different order from their order in memory, and to initialize the same
    element multiple times, with only the final initialization actually
    occurring. This can be convenient for setting up a rule and then adding
    exceptions to that rule.

    But it simply ends up being left to right.

    Why is that it a "but"? If you want to give users control over the order
    of initialization, what is simpler or more natural that using the
    textual order.

    Given { A, B, C }, the members are initialized in order of increasing
    offset address, corresponding to left-to-right order in the syntax.

    Given { [2] = A, [1] = B, [0] = C }, they are initialized in the left-to-right order in the syntax: [2] first, then [1] then [0].

    So we have order. And yet we don't have order; the expressions are not actually sequenced.

    You can always make something sound contradictory or confusing by
    leaving out the details that resolve the contradiction or remove the
    confusion.
    Yes, the initializations of the members of an aggregate object are
    ordered. And also yes, the evaluations of the initializer expressions
    for those objects are unordered, the same as is generally the case -
    there's only a few features of C that impose order on expressions - the semicolon at the ends of declarations or statements are the most common.
    As a general way, whenever you need to order the evaluation of
    expressions that would otherwise be unordered, the way to do so is
    simply put them in a different declarations or statements, which often
    requires creating temperaries to hold the results of intermediate
    evaluations.

    If there weren't a rule mandating the order in
    which initializers were applied, when two or more initializers affect
    the same object, it wouldn't be possible to be certain which one
    overrode the others.

    It would make sense for that simply to be a constraint violation;
    two initializations for the same object are being requested.

    The committee felt otherwise. The standard quite explicitly says: "...
    each initializer provided for a particular subobject overriding any
    previously listed initializer for the same subobject ..." (6.7.10p20). I
    agree - I can see obscure situations where that rule makes the feature
    more convenient. The standard also provides a relevant example where the intended behavior depends upon this feature:

    "EXAMPLE 13 Space can be "allocated" from both ends of an array by using
    a single designator:
    int a[MAX] = {
    1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
    };

    In the above, if MAX is greater than ten, there will be some zero-valued elements in the middle; if it is less than ten, some of the values
    provided by the first five initializers will be overridden by the
    second five."

    If you wanted the behavior to depend upon the value of MAX in precisely
    the fashion provided by this feature, and this feature were not
    available, the code would have to be a lot more complicated.

    There is no sequencing in the initialization: { i++, i++ } would
    be undefined behavior. Yet, you can request multiple initializations
    of the same subobject and have it safely resolved to the rightmost?

    Correct. If you need initializer expressions to be ordered, you'll have
    to put them in different statements or declarations.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rosario19@21:1/5 to Kaz Kylheku on Sat Nov 30 16:41:03 2024
    On Tue, 26 Nov 2024 17:59:08 -0000 (UTC), Kaz Kylheku wrote:

    On 2024-11-25, Rosario19 <Ros@invalid.invalid> wrote:
    On Mon, 25 Nov 2024 18:23:58 -0000 (UTC), Kaz Kylheku wrote:

    void fn(int a)
    {
    int x[3] = { foo(), bar(), a }; /* not in C90 */

    is in the above foo() called before bar()?

    No, you cannot rely on that. Maybe it's fixed in a more recent standard,
    but C99 (which I happen to have open in a PDF reader tab) stated that
    "The order in which any side effects occur among the initialization list >expressions is unspecified.". This implies that there is no sequence
    point between any two initializing expressions, which means we don't
    know whose expression's function call takes place first.

    In any case, a C90 compiler with the above support as an extension to
    C90 can specify rigid sequencing behavior.

    void fn(int a)
    {
    int x[3];
    x[0]=foo(); x[1]=bar(); x[2]=a;

    this would be ok with every C compiler

    One problem is, if you're doing this because your compiler is C90, you
    also have to do something about all declarations which follow the int
    x[3], since they cannot occur after a statement. You can add another
    level of block nesting for them, or whatever.

    int fn(int a)
    { int x[3];
    int b=9;
    x[0]=foo(); x[1]=bar(); x[2]=a;
    return x[0]==0||a==b;
    }

    i don't see onother level of block nesting

    Initialization is preferable to leaving an object uninitialized and >assigning. There is a scope where the name is visible, but the object
    is not initialized, inviting code to be inserted there which tries
    to use it.

    If I needed foo to be called before bar, I would still rather do
    the following than assignment:

    int f = foo();
    int b = bar();
    int x[3] = { f, b, a };

    ok

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)