• Question about struct initializers

    From Kenny McCormack@3:633/10 to All on Mon Aug 17 20:48:21 2026
    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i" member of the struct got init'd to 0?

    I've tested this under various conditions and it always seems to come up 0,
    so it seems pretty consistent.

    --
    "They say if you play a Microsoft CD backwards, you hear satanic messages.
    Thats nothing, cause if you play it forwards, it installs Windows."

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From bart@3:633/10 to All on Mon Aug 17 22:21:05 2026
    On 17/08/2026 21:48, Kenny McCormack wrote:
    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i" member of the struct got init'd to 0?

    I've tested this under various conditions and it always seems to come up 0, so it seems pretty consistent.


    I'm pretty sure it's part of the language. In general if you only
    partially initialise an aggregate type, the remaining elements will be
    zeroed:

    int A[10] = {1, 2}; // inside a function

    The last 8 elements will be zero. This is in contrast to this:

    int B[10];

    where the contents are undefined.

    (Zeroing may or may not mean all-bits zero for floats, pointers, ints
    with padding bits ... but I'm not getting into that.)

    This test shows it better:

    #include <stdio.h>
    #include <string.h>

    int main() {
    for (int i=0; i<10; ++i) {
    int A[10] = {1, 2};
    printf("%d %d\n", A[3], A[7]);
    memset(A, 255, 40);
    }
    }

    Output is consisently 0 0 on each loop, showing the uninitialised array elements are deliberately reset to zero each time around. Take out the initialisation, and they will be undefined first time around, then all 1s.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From bixbox@3:633/10 to All on Mon Aug 17 23:23:48 2026
    gazelle@shell.xmission.com (Kenny McCormack) writes:

    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i" member of the struct got init'd to 0?


    Are you building in debug mode? as far as I remember if I'm not wrong
    debug mode initialize memory to zero or something.

    bix

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Mon Aug 17 21:44:15 2026
    gazelle@shell.xmission.com (Kenny McCormack) writes:
    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i" >member of the struct got init'd to 0?

    Luck. The pages in the stack are zeroed by the operating system
    before main() is invoked[*]. If this code were in a function called
    multiple times, then you will not be guaranteed that the 'i' field
    will have any specific value.

    [*] For security reasons.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Tue Aug 18 01:02:46 2026
    On Mon, 17 Aug 2026 20:48:21 -0000 (UTC)
    gazelle@shell.xmission.com (Kenny McCormack) wrote:

    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the
    "i" member of the struct got init'd to 0?


    Part of the language.
    If automatic variable of struct type has an initializer then all
    "named" fields that are not initialized explicitly are initialized to
    zeros.


    I've tested this under various conditions and it always seems to come
    up 0, so it seems pretty consistent.




    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Tue Aug 18 01:06:52 2026
    On Mon, 17 Aug 2026 21:44:15 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    gazelle@shell.xmission.com (Kenny McCormack) writes:
    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that
    the "i" member of the struct got init'd to 0?

    Luck. The pages in the stack are zeroed by the operating system
    before main() is invoked[*]. If this code were in a function called multiple times, then you will not be guaranteed that the 'i' field
    will have any specific value.

    [*] For security reasons.

    Before giving answer with such level of certainty it's recommended to
    read the relevant document.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 18 06:32:25 2026
    On 18/08/2026 4:48 AM, Kenny McCormack wrote:
    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i" member of the struct got init'd to 0?

    I've tested this under various conditions and it always seems to come up 0, so it seems pretty consistent.


    Before I read the rest of the thread, I'll just add that yes, it's part
    of C. You can even use

    struct foo i = { .i = 13 } ;

    and the i.name will be a null pointer. Or more accurately, anything
    that you don't mention in the /initializer/ gets zeroed.


    Happy coding in C!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    P.S. I'm sure there are many trolls in comp.lang.c who are itch-
    ing to correct me. Let them try!

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Tobin@3:633/10 to All on Mon Aug 17 22:34:32 2026
    In article <PgLgS.12867$AH8e.9826@fx48.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:
    The pages in the stack are zeroed by the operating system
    before main() is invoked[*].

    On most systems they are cleared before the program is started, but
    main() may not be the first thing to run; for example a dynamic
    linker may load in shared libraries.

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that local variables in main() would be zero.

    -- Richard

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 18 06:35:21 2026
    On 18/08/2026 6:02 AM, Michael S wrote:
    On Mon, 17 Aug 2026 20:48:21 -0000 (UTC)
    gazelle@shell.xmission.com (Kenny McCormack) wrote:

    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the
    "i" member of the struct got init'd to 0?


    Part of the language.
    If automatic variable of struct type has an initializer then all
    "named" fields that are not initialized explicitly are initialized to
    zeros.


    I've tested this under various conditions and it always seems to come
    up 0, so it seems pretty consistent.




    Thank you for thumping the standard correctly. In my other followup I
    gave a practical example of just that, using C99 and later syntax.

    For some reason, I believe it was all the usual trolls, were trying to
    upstage one another without actually knowing how C works, in their foll- ow-ups.


    Happy reading comp.lang.c!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 18 06:39:37 2026
    On 18/08/2026 6:34 AM, Richard Tobin wrote:
    In article <PgLgS.12867$AH8e.9826@fx48.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:
    The pages in the stack are zeroed by the operating system
    before main() is invoked[*].

    On most systems they are cleared before the program is started, but
    main() may not be the first thing to run; for example a dynamic
    linker may load in shared libraries.

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that local variables in main() would be zero.

    -- Richard

    Dear Richard,

    I can forgive that lapse in standard C knowledge, because you probably
    didn't read mine nor Michael's followups before writing yours. But
    now that you have, please update your C knowledge.


    Happy coding in C.
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 18 06:45:23 2026
    On 18/08/2026 5:44 AM, Scott Lurndal wrote:
    gazelle@shell.xmission.com (Kenny McCormack) writes:
    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i"
    member of the struct got init'd to 0?

    Luck. The pages in the stack are zeroed by the operating system
    before main() is invoked[*]. If this code were in a function called multiple times, then you will not be guaranteed that the 'i' field
    will have any specific value.

    [*] For security reasons.

    You fucking asshole! You made the mistake of throwing insult my way, so
    now I show you and all of comp.lang.c how utterly moronic you are.

    You're an imbecile, nincompoop, and a troglodyte.


    Go fucking read /21st Century C/ by Klemens, and don't dare write an-
    other followup until you've learned it by heart, you fucking piece of
    shit!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 18 06:46:00 2026
    On 18/08/2026 5:21 AM, bart wrote:
    On 17/08/2026 21:48, Kenny McCormack wrote:
    Consider:

    #include <stdio.h>

    int main(void)
    {
    ÿÿÿÿ struct foo { char *name; int i; } foo = { "This is a test" };
    ÿÿÿÿ printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i"
    member of the struct got init'd to 0?

    I've tested this under various conditions and it always seems to come
    up 0,
    so it seems pretty consistent.


    I'm pretty sure it's part of the language. In general if you only
    partially initialise an aggregate type, the remaining elements will be zeroed:

    ÿ int A[10] = {1, 2};ÿÿÿÿÿÿÿÿÿÿÿ // inside a function

    The last 8 elements will be zero. This is in contrast to this:

    ÿ int B[10];

    where the contents are undefined.

    (Zeroing may or may not mean all-bits zero for floats, pointers, ints
    with padding bits ... but I'm not getting into that.)

    This test shows it better:

    ÿ#include <stdio.h>
    ÿ#include <string.h>

    ÿint main() {
    ÿÿÿÿ for (int i=0; i<10; ++i) {
    ÿÿÿÿÿÿÿÿ int A[10] = {1, 2};
    ÿÿÿÿÿÿÿÿ printf("%d %d\n", A[3], A[7]);
    ÿÿÿÿÿÿÿÿ memset(A, 255, 40);
    ÿÿÿÿ }
    ÿ}

    Output is consisently 0 0 on each loop, showing the uninitialised array elements are deliberately reset to zero each time around. Take out the initialisation, and they will be undefined first time around, then all 1s.


    And you, you fucking piece of shit! Read my followup to Scott, print
    it out, and eat it, you fucking moron!

    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 18 06:47:15 2026
    On 18/08/2026 5:23 AM, bixbox wrote:
    gazelle@shell.xmission.com (Kenny McCormack) writes:

    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i"
    member of the struct got init'd to 0?


    Are you building in debug mode? as far as I remember if I'm not wrong
    debug mode initialize memory to zero or something.

    bix

    Dear bix,

    You are correct that a lot of compilers will add automatic zero init-
    ializers when in debug mode. However, as my esteemed colleague Michael
    S has already pointed out quite succinctly, this is part of how C works.


    Happy coding in C!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Tobin@3:633/10 to All on Mon Aug 17 23:03:59 2026
    In article <K4MgS.476685$4Fu9.200541@fx05.ams4>,
    Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> wrote:
    On 18/08/2026 6:34 AM, Richard Tobin wrote:

    The pages in the stack are zeroed by the operating system
    before main() is invoked[*].

    On most systems they are cleared before the program is started, but
    main() may not be the first thing to run; for example a dynamic
    linker may load in shared libraries.

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that local
    variables in main() would be zero.

    I can forgive that lapse in standard C knowledge, because you probably
    didn't read mine nor Michael's followups before writing yours. But
    now that you have, please update your C knowledge.

    I didn't make any statements about C. Please improve your reading comprehension.

    -- Richard

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Tue Aug 18 11:24:32 2026
    On 18/08/2026 7:03 AM, Richard Tobin wrote:
    In article <K4MgS.476685$4Fu9.200541@fx05.ams4>,
    Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> wrote:
    On 18/08/2026 6:34 AM, Richard Tobin wrote:

    The pages in the stack are zeroed by the operating system
    before main() is invoked[*].

    On most systems they are cleared before the program is started, but
    main() may not be the first thing to run; for example a dynamic
    linker may load in shared libraries.

    Please remind me again which programming language uses main() as the
    starting point?>>>
    When shared libraries were introduced in SunOS in the mid 1980s,

    Last time I checked, SunOS was of the actual Unix heritage, first BSD,
    then AT&T. I presume you mean the SunOS of the BSD lineage, since you
    mention the 80s.
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that local
    variables in main() would be zero.

    The standard Unix utilities are, or were, written in C.>
    I can forgive that lapse in standard C knowledge, because you probably
    didn't read mine nor Michael's followups before writing yours. But
    now that you have, please update your C knowledge.

    I didn't make any statements about C. Please improve your reading comprehension.

    I didn't make any statements about your ability to write. Please im-
    prove your writing comprehension.

    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Tue Aug 18 10:39:45 2026
    On 17/08/2026 23:23, bixbox wrote:
    gazelle@shell.xmission.com (Kenny McCormack) writes:

    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that the "i"
    member of the struct got init'd to 0?


    It's in the language. As soon as you have /some/ initialisation for a
    local struct or array, every part of it is initialised - missing
    initialisers are treated as zero initialisation (the same as you get for file-scope objects). It's common to write "int xs[10] = { 0 };", and
    the like.

    With C23, you can also use an empty initialiser "{}", and have it all zero-initialised.


    Are you building in debug mode? as far as I remember if I'm not wrong
    debug mode initialize memory to zero or something.


    C does not have any concept of "debug mode". Many /compilers/ have
    flags that can add extra debug information or even run-time checks to
    help find problems, but there is no change in the semantics. The C code
    means what it means, unaffected by compiler flags unless they are
    actually changing the language.

    A compiler that set ".i" to 0 here in a "debug" mode, but did not do so
    in "release" or "optimised" modes, would be doing the developer a
    terrible disservice. It would lead to misunderstandings, and mean that
    bugs involved change entirely when you switch between modes. I am not a
    fan of separate "debug" and "release" modes at the best of times, but
    having different semantics in these modes sounds particularly bad.



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Tue Aug 18 11:11:56 2026
    On 18/08/2026 00:06, Michael S wrote:
    On Mon, 17 Aug 2026 21:44:15 GMT
    scott@slp53.sl.home (Scott Lurndal) wrote:

    gazelle@shell.xmission.com (Kenny McCormack) writes:
    Consider:

    #include <stdio.h>

    int main(void)
    {
    struct foo { char *name; int i; } foo = { "This is a test" };
    printf("foo.name = '%s', foo.i = %d\n",foo.name,foo.i);
    }

    Running this generates the expected output of "This is a test" and 0.

    But the question is: Is it part of the language or just luck that
    the "i" member of the struct got init'd to 0?

    Luck. The pages in the stack are zeroed by the operating system
    before main() is invoked[*]. If this code were in a function called
    multiple times, then you will not be guaranteed that the 'i' field
    will have any specific value.

    [*] For security reasons.

    Before giving answer with such level of certainty it's recommended to
    read the relevant document.


    Indeed. The important paragraph is 6.7.9p21 in C11 (or 6.7.11p22 in C23
    - unfortunately many paragraph numbers changed a bit in C23):

    """
    If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string
    literal used to initialize an array of known size than there are
    elements in the array, the remainder of the aggregate shall be
    initialized implicitly the same as objects that have static storage
    duration.
    """

    The text is basically the same from C89/C90 onwards - I have not checked
    K&R.




    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Tue Aug 18 11:16:04 2026
    On 18/08/2026 00:34, Richard Tobin wrote:
    In article <PgLgS.12867$AH8e.9826@fx48.iad>,
    Scott Lurndal <slp53@pacbell.net> wrote:
    The pages in the stack are zeroed by the operating system
    before main() is invoked[*].

    On most systems they are cleared before the program is started, but
    main() may not be the first thing to run; for example a dynamic
    linker may load in shared libraries.

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that local variables in main() would be zero.


    That's all true for local variables in general - uninitialised local
    variables have unspecified values, and trying to use those values is UB
    and likely to end in tears.

    But the OP's question was not about uninitialised local variables - it
    was about a local struct with explicit initialisers for only some of its fields. The rules of C do not allow a "partially initialised" object -
    the whole struct is initialised, with the remaining fields
    zero-initialised. (Padding is also initialised to 0 bits.)



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Tue Aug 18 11:19:26 2026
    On 18/08/2026 01:03, Richard Tobin wrote:
    In article <K4MgS.476685$4Fu9.200541@fx05.ams4>,
    Johann 'Myrkraverk' Oskarsson <johann@myrkraverk.invalid> wrote:

    I didn't make any statements about C. Please improve your reading comprehension.


    Please don't reply to Johann. Most people have either killfiled him
    entirely, or simply ignore his posts. His other posts in this thread
    should make it perfectly clear why.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Tue Aug 18 03:58:51 2026
    David Brown <david.brown@hesbynett.no> writes:
    [...]
    Indeed. The important paragraph is 6.7.9p21 in C11 (or 6.7.11p22 in
    C23 - unfortunately many paragraph numbers changed a bit in C23):

    """
    If there are fewer initializers in a brace-enclosed list than there
    are elements or members of an aggregate, or fewer characters in a
    string literal used to initialize an array of known size than there
    are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage
    duration.
    """

    The text is basically the same from C89/C90 onwards - I have not
    checked K&R.

    K&R1, Appendix A, Section 8.6 (1978):

    When the declared variable is an aggregate (a structure or
    array) then the initializer consists of a brace-enclosed,
    comma-separated list of initializers for the members of
    the aggregate, written in increasing subscript or member
    order. If the aggregate contains subaggregates, this rule
    applies recursively to the members of the aggregate. If there
    are fewer initializers in the list than there are members of
    the aggregate, then the aggregate is padded with 0's. It is
    not permitted to initialize unions or automatic aggregates.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Tue Aug 18 22:45:35 2026
    On Mon, 17 Aug 2026 22:34:32 -0000 (UTC), Richard Tobin wrote:

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that
    local variables in main() would be zero.

    How would those shared libraries be seeing local variables in main(),
    given that no part of main() has yet executed to pass any references
    to them?

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Tobin@3:633/10 to All on Wed Aug 19 00:08:54 2026
    In article <1162naf$26tip$4@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that
    local variables in main() would be zero.

    How would those shared libraries be seeing local variables in main(),
    given that no part of main() has yet executed to pass any references
    to them?

    It wasn't the shared libraries themselves, but the dynamic linker
    that loaded the shared libraries, though that's not important.

    Running before main(), it used the stack for its own local variables,
    with the result that when main() was called the stack was no longer
    all zero.

    -- Richard

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Tue Aug 18 17:13:34 2026
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Mon, 17 Aug 2026 22:34:32 -0000 (UTC), Richard Tobin wrote:
    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that
    local variables in main() would be zero.

    How would those shared libraries be seeing local variables in main(),
    given that no part of main() has yet executed to pass any references
    to them?

    Code in shared libraries wouldn't see local variables in main(),
    but it might write to memory that's later used to store local
    variables in main(). Think about a shared library's initialization
    code calling a function that has its own local variables. If main()
    is guaranteed to be the first thing that's invoked, that stack space
    is going to be "fresh" on the first invocation. Shared libraries
    can violate that assumption.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Wed Aug 19 04:32:38 2026
    On Wed, 19 Aug 2026 00:08:54 -0000 (UTC), Richard Tobin wrote:

    In article <1162naf$26tip$4@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that
    local variables in main() would be zero.

    How would those shared libraries be seeing local variables in
    main(), given that no part of main() has yet executed to pass any
    references to them?

    It wasn't the shared libraries themselves, but the dynamic linker
    that loaded the shared libraries, though that's not important.

    Running before main(), it used the stack for its own local
    variables, with the result that when main() was called the stack was
    no longer all zero.

    Again, that doesn?t seem to make sense.

    Checking my copy of K&R, section 1.10 ?External Variables and Scope?,
    first of all it makes clear that variables local to main() are no
    different to those in any other function:

    The variables in `main`, such as `line`, `longest`, etc., are
    private or local to `main`. Because they are declared within main,
    no other function can have direct access to them. The same is true
    of the variables in other functions; for example, the variable `i`
    in `getline` is unrelated to the `i` in copy. Each local variable
    in a function comes into existence only when the function is
    called, and disappears when the function is exited. This is why
    such variables are usually known as _automatic_ variables,
    following terminology in other languages.

    And then it says:

    Because automatic variables come and go with function invocation,
    they do not retain their values from one call to the next, and
    must be explicitly set upon each entry. If they are not set, they
    will contain garbage.

    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Tue Aug 18 22:34:09 2026
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Wed, 19 Aug 2026 00:08:54 -0000 (UTC), Richard Tobin wrote:
    In article <1162naf$26tip$4@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently) that
    local variables in main() would be zero.

    How would those shared libraries be seeing local variables in
    main(), given that no part of main() has yet executed to pass any
    references to them?

    It wasn't the shared libraries themselves, but the dynamic linker
    that loaded the shared libraries, though that's not important.

    Running before main(), it used the stack for its own local
    variables, with the result that when main() was called the stack was
    no longer all zero.

    Again, that doesn?t seem to make sense.

    Checking my copy of K&R, section 1.10 ?External Variables and Scope?,
    first of all it makes clear that variables local to main() are no
    different to those in any other function:

    The variables in `main`, such as `line`, `longest`, etc., are
    private or local to `main`. Because they are declared within main,
    no other function can have direct access to them. The same is true
    of the variables in other functions; for example, the variable `i`
    in `getline` is unrelated to the `i` in copy. Each local variable
    in a function comes into existence only when the function is
    called, and disappears when the function is exited. This is why
    such variables are usually known as _automatic_ variables,
    following terminology in other languages.

    And then it says:

    Because automatic variables come and go with function invocation,
    they do not retain their values from one call to the next, and
    must be explicitly set upon each entry. If they are not set, they
    will contain garbage.

    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    The language clearly makes no such guarantee. The point is that some
    software made that assumption, perhaps accidentally, and happened
    to "work" before the introduction of shared libraries but visibly
    failed after.

    Assume that the memory to be used as the "stack" (storage for objects
    with automatic storage duration) is zeroed by the implementation
    before program startup.

    Before shared libraries, the initial invocation of the main()
    function would allocate its local variables in "fresh" memory
    that was just zeroed. Code that incorrectly assumes automatic
    objects are zeroed will "work". (It could have failed on another implementation that initializes stack to something other than zero.)

    After shared libraries, shared library initialization code is likely
    to run before main() is entered. By the time main() starts, the
    memory it uses for its local variables has already been clobbered.

    Again, the shared library code has no access to the named variables
    defined within main(), but it does have access to the memory that will
    later be allocated for them.

    All of this is implementation-specific (not "implementation-defined"
    as the standard uses the term), so you won't find anything about it
    in the language standard.

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Tobin@3:633/10 to All on Wed Aug 19 12:21:15 2026
    In article <1163bl5$2c1o2$1@dont-email.me>, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    Quite so.

    I was responding to Scott's mistaken explanation of why the
    trailing struct members are zero:

    Luck. The pages in the stack are zeroed by the operating system
    before main() is invoked

    It's not luck, they're zero because they are in fact initialized, as
    several people said. But Scott's explanation implies that even
    uninitialized variables in main() are zero because of the operating
    system zeroing the stack and main() being the first function to be
    called. In the early days of C, this was often so, and some programs
    wrongly depended on it. In some of those cases the mistake became
    apparent when shared libraries were introduced, because of the dynamic
    linker running before main().

    -- Richard

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Wed Aug 19 14:33:10 2026
    On 19/08/2026 14:21, Richard Tobin wrote:
    In article <1163bl5$2c1o2$1@dont-email.me>, Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    Quite so.

    I was responding to Scott's mistaken explanation of why the
    trailing struct members are zero:

    Luck. The pages in the stack are zeroed by the operating system
    before main() is invoked

    It's not luck, they're zero because they are in fact initialized, as
    several people said. But Scott's explanation implies that even
    uninitialized variables in main() are zero because of the operating
    system zeroing the stack and main() being the first function to be
    called. In the early days of C, this was often so, and some programs
    wrongly depended on it. In some of those cases the mistake became
    apparent when shared libraries were introduced, because of the dynamic
    linker running before main().


    I think Scott was saying that uninitialised local variables often are
    zero, at least for main(), rather than suggestion that they always are.
    (And you are correct that some people make/made the assumption that they
    were always zero, causing trouble later.)

    Although he has not said as much himself, I expect that Scott replied
    without reading the OP's post well enough, and jumped to the assumption
    that it was talking about uninitialised local variables rather than
    missing initialisers for an aggregate.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Wed Aug 19 14:53:44 2026
    David Brown <david.brown@hesbynett.no> writes:
    On 19/08/2026 14:21, Richard Tobin wrote:
    In article <1163bl5$2c1o2$1@dont-email.me>, Lawrence D'Oliveiro
    <ldo@nz.invalid> wrote:

    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    Quite so.

    I was responding to Scott's mistaken explanation of why the
    trailing struct members are zero:

    Luck. The pages in the stack are zeroed by the operating system
    before main() is invoked

    It's not luck, they're zero because they are in fact initialized, as
    several people said. But Scott's explanation implies that even
    uninitialized variables in main() are zero because of the operating
    system zeroing the stack and main() being the first function to be
    called. In the early days of C, this was often so, and some programs
    wrongly depended on it. In some of those cases the mistake became
    apparent when shared libraries were introduced, because of the dynamic
    linker running before main().


    I think Scott was saying that uninitialised local variables often are
    zero, at least for main(), rather than suggestion that they always are.
    (And you are correct that some people make/made the assumption that they >were always zero, causing trouble later.)

    Although he has not said as much himself, I expect that Scott replied >without reading the OP's post well enough, and jumped to the assumption
    that it was talking about uninitialised local variables rather than
    missing initialisers for an aggregate.


    Yes, that is a correct summary of my reply. And has been pointed out,
    code that runs prior to main may leave non-zero values on the stack.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Wed Aug 19 12:25:58 2026
    On 8/18/2026 9:32 PM, Lawrence D?Oliveiro wrote:
    [...]
    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    char buf[4096];

    vs

    char buf[4096] = { '\0' };


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Thu Aug 20 04:07:54 2026
    On 20/08/2026 3:25 AM, Chris M. Thomasson wrote:
    On 8/18/2026 9:32 PM, Lawrence D?Oliveiro wrote:
    [...]
    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    char buf[4096];

    vs

    char buf[4096] = { '\0' };


    The lack of spaces before and after 4096 implies this comes from
    ChatGPT, or are you using Copilot now?

    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Thu Aug 20 04:10:25 2026
    On 20/08/2026 3:25 AM, Chris M. Thomasson wrote:
    On 8/18/2026 9:32 PM, Lawrence D?Oliveiro wrote:
    [...]
    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    char buf[4096];

    vs

    char buf[4096] = { '\0' };


    The lack of spaces before and after 4096 indicate this code came from
    Copilot, or are you using ChatGPT to code for you these days?

    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Wed Aug 19 13:17:26 2026
    On 8/19/2026 1:07 PM, Johann 'Myrkraverk' Oskarsson wrote:
    On 20/08/2026 3:25 AM, Chris M. Thomasson wrote:
    On 8/18/2026 9:32 PM, Lawrence D?Oliveiro wrote:
    [...]
    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    char buf[4096];

    vs

    char buf[4096] = { '\0' };


    The lack of spaces before and after 4096 implies this comes from
    ChatGPT, or are you using Copilot now?


    Huh? Are you a full blown moron, our just an idiot?


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Thu Aug 20 04:27:31 2026
    On 20/08/2026 4:17 AM, Chris M. Thomasson wrote:
    On 8/19/2026 1:07 PM, Johann 'Myrkraverk' Oskarsson wrote:
    On 20/08/2026 3:25 AM, Chris M. Thomasson wrote:
    On 8/18/2026 9:32 PM, Lawrence D?Oliveiro wrote:
    [...]
    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    char buf[4096];

    vs

    char buf[4096] = { '\0' };


    The lack of spaces before and after 4096 implies this comes from
    ChatGPT, or are you using Copilot now?


    Huh? Are you a full blown moron, our just an idiot?


    Thank you for confirming you never write your own code!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Wed Aug 19 23:29:14 2026
    On Wed, 19 Aug 2026 12:21:15 -0000 (UTC), Richard Tobin wrote:

    In the early days of C, this was often so, and some programs wrongly
    depended on it. In some of those cases the mistake became apparent
    when shared libraries were introduced, because of the dynamic linker
    running before main().

    I still don?t understand the connection with dynamic linking.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Wed Aug 19 17:43:13 2026
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Wed, 19 Aug 2026 12:21:15 -0000 (UTC), Richard Tobin wrote:
    In the early days of C, this was often so, and some programs wrongly
    depended on it. In some of those cases the mistake became apparent
    when shared libraries were introduced, because of the dynamic linker
    running before main().

    I still don?t understand the connection with dynamic linking.

    Oh? I thought it had been explained clearly enough, several times.

    The idea is that dynamic linking introduced the possibility of
    initialization code from dynamic libraries being invoked before
    main() is called. I've already explained how this can clobber the
    memory that's used for local variables when main() runs.

    Without dynamic linking, main() is the first code that runs when
    the program is executed. It allocates its local variables in memory
    that's been zeroed by the OS.

    With dynamic linking, code other than main() (library startup code)
    can be invoked before main() is entered. This code can store
    non-zero values in the same memory that main() will later use for
    its local variables. (Function calls are executed and completed
    before main() starts, leaving stale data above the top of the stack.)

    If main() *unsafely* assumes that uninitialized local variables
    are zeroed, it can appear to work correctly without dynamic linking
    and fail with dynamic linking.

    I just did a quick experiment on Ubuntu with gcc, and found that
    the same thing can happen with static libraries, using gcc's `__attribute__((constructor))`. The discussion was about SunOS in
    the mid 1980s, so things were likely different. I can imagine that,
    in SunOS, dynamic linking was the only way for code to be executed
    before main() is entered. Or perhaps it just became more common.

    Is any of this still unclear?

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Kenny McCormack@3:633/10 to All on Thu Aug 20 02:00:25 2026
    In article <116473r$hal8$1@artemis.inf.ed.ac.uk>,
    Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    ...
    In the early days of C, this was often so, and some programs
    wrongly depended on it. In some of those cases the mistake became
    apparent when shared libraries were introduced, because of the dynamic
    linker running before main().

    It would have been clearer (although it was certainly clear enough for
    anyone with a triple digit IQ, but LDO seems not to have reached that
    level) if this had been explained in terms of the introduction of the
    dynamic linker running before main() is called - rather than in terms of
    the introduction of shared libs. Using the term "shared libraries" as a
    proxy for "the dynamic linker" begat the possibility of confusion on the
    part of careless readers.

    And besides, it seems to me that even without either "shared libraries" or
    a "dynamic linker", it has always been the case that non-main() code runs before main is called. C is usually implemented as a bit of startup code (often stored in crt0.lib or some such) that does stuff, then does a "call"
    of "main". So that startup code could easily corrupt the (formerly
    pristine) "stack".

    Note, incidentally, that "the s word" must always be enclosed in scare
    quotes in this newsgroup.

    --
    When someone tells me he/she is a Christian I check to see if I'm
    still in possession of my wallet.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Thu Aug 20 13:16:23 2026
    Subject: Why are you picking on Lawrence? (was: Re: Question about struct initializers)

    On 20/08/2026 10:00 AM, Kenny McCormack wrote:
    In article <116473r$hal8$1@artemis.inf.ed.ac.uk>,
    Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    ...
    In the early days of C, this was often so, and some programs
    wrongly depended on it. In some of those cases the mistake became
    apparent when shared libraries were introduced, because of the dynamic
    linker running before main().

    It would have been clearer (although it was certainly clear enough for
    anyone with a triple digit IQ, but LDO seems not to have reached that
    level) if this had been explained in terms of the introduction of the
    Why are you picking on Lawrence? The guy is a Python influencer, not a programmer, and now you are pretending he should know how binary code,
    or at least assembly should behave?

    Dear Lawrence, and anyone else still confused about how these /shared libraries/ "corrupt" the stack before main(),

    We can go over this quite clearly in comp.lang.asm at a later date.
    I'll use a S.P.I.M. compatible core for the examples.


    Happy assembly coding!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Tobin@3:633/10 to All on Thu Aug 20 09:56:04 2026
    In article <1165ij1$33a5h$1@kst.eternal-september.org>,
    Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:

    I just did a quick experiment on Ubuntu with gcc, and found that
    the same thing can happen with static libraries, using gcc's >`__attribute__((constructor))`. The discussion was about SunOS in
    the mid 1980s, so things were likely different. I can imagine that,
    in SunOS, dynamic linking was the only way for code to be executed
    before main() is entered. Or perhaps it just became more common.

    Yes, before that the startup code did little more than:

    exit(main(argc, argv, envp));

    -- Richard

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Richard Tobin@3:633/10 to All on Thu Aug 20 10:14:42 2026
    In article <1165n3p$3589c$1@news.xmission.com>,
    Kenny McCormack <gazelle@shell.xmission.com> wrote:
    In article <116473r$hal8$1@artemis.inf.ed.ac.uk>,
    Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    ...
    In the early days of C, this was often so, and some programs
    wrongly depended on it. In some of those cases the mistake became
    apparent when shared libraries were introduced, because of the dynamic >>linker running before main().

    It would have been clearer (although it was certainly clear enough for
    anyone with a triple digit IQ, but LDO seems not to have reached that
    level) if this had been explained in terms of the introduction of the
    dynamic linker running before main() is called - rather than in terms of
    the introduction of shared libs. Using the term "shared libraries" as a
    proxy for "the dynamic linker" begat the possibility of confusion on the
    part of careless readers.

    If you refer back you will see that the first thing I said was:

    On most systems they are cleared before the program is started, but
    main() may not be the first thing to run; for example a dynamic
    linker may load in shared libraries.

    And besides, it seems to me that even without either "shared libraries" or
    a "dynamic linker", it has always been the case that non-main() code runs >before main is called. C is usually implemented as a bit of startup code >(often stored in crt0.lib or some such) that does stuff, then does a "call" >of "main". So that startup code could easily corrupt the (formerly
    pristine) "stack".

    It certainly *could*, but as it happens in the common unix
    implementations of the time it didn't. If you're interested, various
    early versions of crt0.c can readily be found at www.tuhs.org. They
    depend on very implementation-specific behaviour, notably declaring a
    local struct variable that will happen to be at the location where the operating system places pointers to the arguments and environment.

    -- Richard

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Thu Aug 20 13:37:01 2026
    On 20/08/2026 04:00, Kenny McCormack wrote:
    In article <116473r$hal8$1@artemis.inf.ed.ac.uk>,
    Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    ...
    In the early days of C, this was often so, and some programs
    wrongly depended on it. In some of those cases the mistake became
    apparent when shared libraries were introduced, because of the dynamic
    linker running before main().

    It would have been clearer (although it was certainly clear enough for
    anyone with a triple digit IQ, but LDO seems not to have reached that
    level) if this had been explained in terms of the introduction of the
    dynamic linker running before main() is called - rather than in terms of
    the introduction of shared libs. Using the term "shared libraries" as a
    proxy for "the dynamic linker" begat the possibility of confusion on the
    part of careless readers.

    And besides, it seems to me that even without either "shared libraries" or
    a "dynamic linker", it has always been the case that non-main() code runs before main is called. C is usually implemented as a bit of startup code (often stored in crt0.lib or some such) that does stuff, then does a "call" of "main". So that startup code could easily corrupt the (formerly
    pristine) "stack".

    That's certainly possible. As well as any dynamic linker stuff, there
    can be constructors run pre-main. Even if your own code is pure C,
    maybe there are static libraries linked in that were written in C++ or
    other languages, or which made use of gcc's
    "__attribute__((constructor))". A C standard library could also run
    code for things like sorting out stdin/stdout, setting up a heap, or
    anything else it fancies before calling main(). And some embedded
    toolchains may do even more odd things before main() is called.

    Other systems may consistently deliver main() a zeroed stack as
    guaranteed behaviour.


    Note, incidentally, that "the s word" must always be enclosed in scare
    quotes in this newsgroup.


    I think it is okay to drop the scare quotation marks when we are talking explicitly about stacks. I have used C on a microcontroller without a
    stack (without any ram at all, in fact), but I think your example code
    would be too big to fit in the code flash. C systems can be assumed to
    use a stack unless the code also has to work on the DS9000.

    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this thread!)



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Kenny McCormack@3:633/10 to All on Thu Aug 20 11:53:46 2026
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brown <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this thread!)

    Heh heh. Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it seemed odd that it worked (*). Unless it was actually part of the language, as it now seems it is.

    (*) Worked in the sense that it was always 0. Not that the code was
    relying on that, of course.

    --
    A 70 year old man who watches 6 hours of TV a day, plays a lot of golf
    and seems to always be in Florida is a retiree, not a president.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Kenny McCormack@3:633/10 to All on Thu Aug 20 11:54:34 2026
    In article <1166k2i$ir8p$2@artemis.inf.ed.ac.uk>,
    Richard Tobin <richard@cogsci.ed.ac.uk> wrote:
    ...
    It certainly *could*, but as it happens in the common unix
    implementations of the time it didn't. If you're interested, various
    early versions of crt0.c can readily be found at www.tuhs.org. They
    depend on very implementation-specific behaviour, notably declaring a
    local struct variable that will happen to be at the location where the >operating system places pointers to the arguments and environment.

    Interesting. Thanks.

    --
    "The most unsettling aspect of my atheism for Christians is
    when they realize that their Bible has no power to make me
    wince. They are used to using it like a cattle prod to get
    people to cower into compliance." - Author unknown

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Thu Aug 20 14:42:17 2026
    On 20/08/2026 13:53, Kenny McCormack wrote:
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brown <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this thread!)

    Heh heh. Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it seemed odd that it worked (*). Unless it was actually part of the language, as it now seems it is.

    (*) Worked in the sense that it was always 0. Not that the code was
    relying on that, of course.


    Now you know you /can/ rely on it.

    Well, you can rely on it if your compiler is following the standards
    here. But I'd be a little surprised to hear of a compiler that got this wrong, unless it was a poor quality embedded toolchain.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Thu Aug 20 14:53:36 2026
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Wed, 19 Aug 2026 12:21:15 -0000 (UTC), Richard Tobin wrote:
    In the early days of C, this was often so, and some programs wrongly
    depended on it. In some of those cases the mistake became apparent
    when shared libraries were introduced, because of the dynamic linker
    running before main().

    I still don?t understand the connection with dynamic linking.

    Oh? I thought it had been explained clearly enough, several times.

    The idea is that dynamic linking introduced the possibility of
    initialization code from dynamic libraries being invoked before
    main() is called. I've already explained how this can clobber the
    memory that's used for local variables when main() runs.

    Without dynamic linking, main() is the first code that runs when
    the program is executed. It allocates its local variables in memory
    that's been zeroed by the OS.

    Even without dynamic linking, the CRT (C Run-time) code will execute
    before main() (often at a symbol called _start). I don't recall
    any guarantee that the CRT code won't use the stack prior to invoking main.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Thu Aug 20 12:21:19 2026
    On 8/19/2026 1:27 PM, Johann 'Myrkraverk' Oskarsson wrote:
    On 20/08/2026 4:17 AM, Chris M. Thomasson wrote:
    On 8/19/2026 1:07 PM, Johann 'Myrkraverk' Oskarsson wrote:
    On 20/08/2026 3:25 AM, Chris M. Thomasson wrote:
    On 8/18/2026 9:32 PM, Lawrence D?Oliveiro wrote:
    [...]
    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    char buf[4096];

    vs

    char buf[4096] = { '\0' };


    The lack of spaces before and after 4096 implies this comes from
    ChatGPT, or are you using Copilot now?


    Huh? Are you a full blown moron, our just an idiot?


    Thank you for confirming you never write your own code!

    Sigh. I write all my own code. Its a shame that you as are you are. You
    should beware of the ai... Anyway, plonk.



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Thu Aug 20 12:24:07 2026
    On 8/19/2026 10:16 PM, Johann 'Myrkraverk' Oskarsson wrote:
    [...]
    Happy assembly coding!

    rofl!


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Thu Aug 20 12:26:40 2026
    On 8/20/2026 4:53 AM, Kenny McCormack wrote:
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brown <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this thread!)

    Heh heh. Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it seemed odd that it worked (*). Unless it was actually part of the language, as it now seems it is.

    (*) Worked in the sense that it was always 0. Not that the code was
    relying on that, of course.


    simply never assume that a in say:

    int a;

    equals zero. Its fairly simple.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Keith Thompson@3:633/10 to All on Thu Aug 20 13:34:59 2026
    scott@slp53.sl.home (Scott Lurndal) writes:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence Dƒ??Oliveiro <ldo@nz.invalid> writes:
    On Wed, 19 Aug 2026 12:21:15 -0000 (UTC), Richard Tobin wrote:
    In the early days of C, this was often so, and some programs wrongly
    depended on it. In some of those cases the mistake became apparent
    when shared libraries were introduced, because of the dynamic linker
    running before main().

    I still donƒ??t understand the connection with dynamic linking.

    Oh? I thought it had been explained clearly enough, several times.

    The idea is that dynamic linking introduced the possibility of >>initialization code from dynamic libraries being invoked before
    main() is called. I've already explained how this can clobber the
    memory that's used for local variables when main() runs.

    Without dynamic linking, main() is the first code that runs when
    the program is executed. It allocates its local variables in memory
    that's been zeroed by the OS.

    Even without dynamic linking, the CRT (C Run-time) code will execute
    before main() (often at a symbol called _start). I don't recall
    any guarantee that the CRT code won't use the stack prior to invoking main.

    Certainly. Just yesterday I wrote a toy test program using static
    linking that invoked code before entry to main(), using gcc's `__attribute__((constructor))`.

    As for _start() calling main(), that wouldn't necessarily cause
    an issue. There would be an issue only if some function is called
    *and returns* before main() is entered.

    The situation that started this subthread happened on SunOS in
    the 1980s. Richard Tobin wrote:

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently)
    that local variables in main() would be zero.

    Apparently the introduction of shared/dynamic libraries either
    introduced the possibility of code being executed before main(),
    or made it more likely.

    (If any such code has visible behavior, that might raise questions
    about conformance.)

    --
    Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
    void Void(void) { Void(); } /* The recursive call of the void */

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Thu Aug 20 21:00:28 2026
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    scott@slp53.sl.home (Scott Lurndal) writes:

    As for _start() calling main(), that wouldn't necessarily cause
    an issue. There would be an issue only if some function is called
    *and returns* before main() is entered.

    Usually the C library function that initializes stdio (stdin,
    stdout and stderr) will be called from the CRT before invoking
    main. I should have been more explicit, I guess.


    The situation that started this subthread happened on SunOS in
    the 1980s. Richard Tobin wrote:

    When shared libraries were introduced in SunOS in the mid 1980s,
    numerous programs including standard unix utilities had to be
    corrected because they had assumed (probably inadvertently)
    that local variables in main() would be zero.

    Apparently the introduction of shared/dynamic libraries either
    introduced the possibility of code being executed before main(),
    or made it more likely.

    Looking at unixware2.0 , they had two i386 crt0.s implementations, one
    for standalone:

    =================
    /
    / start()
    /
    / Entry point for standalone programs. Standalone runs
    / in a flat 4 Gig segment with interrupts disabled.
    / Prior to starting up the program it must have a stack
    / initialized, the SLIC initialized, and its BSS cleared.
    /
    .text
    .globl start
    .align 4
    start:
    movl CD_LOC+c_bottom,%esp /* set initial stack pointer */
    CALL slic_init /* set up slic stuff */
    .L1: CALL clearbss /* clear our own bss */
    CALL main /* do the work */
    pushl %eax /* return value */
    .L2: CALL exit /* exit */
    jmp .L2 /* should not happen */

    /* relative speed of machine */
    .data
    .align 4
    .globl cpuspeed
    cpuspeed:
    .long 8 /* XXX is this really needed? */ ==================

    And one for hosted:

    ==================
    _fgdef_(_start):
    / Allocate a NULL return address and a NULL previous %ebp as if
    / there was a genuine call to _start.
    / sdb stack trace shows _start(argc,argv[0],argv[1],...,envp[0],...)
    pushl $0
    pushl $0
    movl %esp,%ebp / The first stack frame.
    pushl %edx / Save _rt_do_exit

    movl $_cleanup,%eax
    testl %eax,%eax
    jz .L0
    pushl $_cleanup
    call atexit
    addl $4,%esp
    .L0:
    movl $_DYNAMIC,%eax
    testl %eax,%eax
    jz .L1
    call atexit
    .L1:
    pushl $_fini
    call atexit

    / Calculate the location of the envp array by adding the size of
    / the argv array to the start of the argv array.
    movl 8(%ebp),%eax / argc
    leal [PTRSIZE\*4](%ebp,%eax,4),%edx /envp
    movl %edx,environ / copy to environ
    pushl %edx
    leal [PTRSIZE\*3](%ebp),%edx / argv
    pushl %edx
    pushl %eax / argc
    call _init
    call __fpstart
    call main / main(argc,argv,envp)
    addl $12,%esp / let sdb know how many args in call to main()
    pushl %eax / and call exit
    call exit
    pushl $0 / Spare word for retaddr before arg
    movl $EXIT,%eax / if user redefined exit, do the
    lcall $0x7,$0 / system call here
    hlt

    ==========

    Granted this is for POSIX/Unix systems, and may be different for
    the other popular programming environment (windows), although
    I wouldn't be surpised to find windows does a bit more before
    calling main.



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From tTh@3:633/10 to All on Fri Aug 21 05:43:25 2026
    On 8/20/26 23:00, Scott Lurndal wrote:
    / Prior to starting up the program it must have a stack
    / initialized, the SLIC initialized, and its BSS cleared.
    /

    What is the SLIC ?

    --
    ** **
    * tTh des Bourtoulots *
    * http://maison.tth.netlib.re/ *
    ** **

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Fri Aug 21 12:51:23 2026
    Subject: Fuck you, and fuck you too (was: Re: Question about struct initializers)

    On 21/08/2026 3:21 AM, Chris M. Thomasson wrote:
    On 8/19/2026 1:27 PM, Johann 'Myrkraverk' Oskarsson wrote:
    On 20/08/2026 4:17 AM, Chris M. Thomasson wrote:
    On 8/19/2026 1:07 PM, Johann 'Myrkraverk' Oskarsson wrote:
    On 20/08/2026 3:25 AM, Chris M. Thomasson wrote:
    On 8/18/2026 9:32 PM, Lawrence D?Oliveiro wrote:
    [...]
    So there can be no assumption that the variables in main() are
    initially zero, unless they are explicitly initialized that way.

    char buf[4096];

    vs

    char buf[4096] = { '\0' };


    The lack of spaces before and after 4096 implies this comes from
    ChatGPT, or are you using Copilot now?


    Huh? Are you a full blown moron, our just an idiot?


    Thank you for confirming you never write your own code!

    Sigh. I write all my own code. Its a shame that you as are you are. You should beware of the ai... Anyway, plonk.



    No you don't. "buf[4096]" lacks spaces around 4096. It's much more
    natural for humans to write

    char buf[ 4096 ] ;

    because now you can see at a glance what the number is, and don't need
    to copy and paste it into ChatGPT to read it aloud for you.

    And "char buf[4096];" is I.D.E.-ism. It's impossible to get I.D.Es.,
    in my considerable experience, to not remove spaces inside ""s, []s, and
    the like. That's why ChatGPT, Copilot, Siri, and the like only ever
    generate code without extraneous spaces for legibility purposes.[1]

    So now I have conclusively proved that you 1) do not write your own
    code, 2) never use a proper text editor like the pre-eminent T.E.C.O.,
    Emacs -- GNU or otherwise --, or even V.I.M; 3) and always use a L.L.M.
    to generate your code because you're too lasy to type. Q.E.D.


    So fuck you too!

    [1] Yes, Dan Cross, I have this vocabulary, so fuck you.
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Fri Aug 21 09:22:18 2026
    On 20/08/2026 21:26, Chris M. Thomasson wrote:
    On 8/20/2026 4:53 AM, Kenny McCormack wrote:
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brownÿ <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this thread!)

    Heh heh.ÿ Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it
    seemed odd
    that it worked (*).ÿ Unless it was actually part of the language, as
    it now
    seems it is.

    (*) Worked in the sense that it was always 0.ÿ Not that the code was
    relying on that, of course.


    simply never assume that a in say:

    int a;

    equals zero. Its fairly simple.

    That only applies to non-static local variables. Program lifetime data
    is always initialised. Code can happily rely on initialisation
    happening as required by the rules of the C language.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Scott Lurndal@3:633/10 to All on Fri Aug 21 14:56:23 2026
    tTh <tth@none.invalid> writes:
    On 8/20/26 23:00, Scott Lurndal wrote:
    / Prior to starting up the program it must have a stack
    / initialized, the SLIC initialized, and its BSS cleared.
    /

    What is the SLIC ?

    Most likley the Sequent SLIC (System Link and Interrupt Controller)[*].

    [*] Thanks to google AI.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Sat Aug 22 00:26:34 2026
    On 21/08/2026 3:22 PM, David Brown wrote:
    On 20/08/2026 21:26, Chris M. Thomasson wrote:
    On 8/20/2026 4:53 AM, Kenny McCormack wrote:
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brownÿ <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this thread!) >>>
    Heh heh.ÿ Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it
    seemed odd
    that it worked (*).ÿ Unless it was actually part of the language, as
    it now
    seems it is.

    (*) Worked in the sense that it was always 0.ÿ Not that the code was
    relying on that, of course.


    simply never assume that a in say:

    int a;

    equals zero. Its fairly simple.

    That only applies to non-static local variables.ÿ Program lifetime data
    is always initialised.ÿ Code can happily rely on initialisation
    happening as required by the rules of the C language.


    Until we run into reality. Compilers have bugs. Did you know Sun's C++ compiler did not support single statement extern "C"? I'll give you an example,

    extern "C" int foo ;

    would not compile. However,

    extern "C" { int foo ; }

    would. They completely forgot to thump their standard, back an the Sun compiler team. And by the time Oracle bought Sun, I had no indication
    this had been fixed; and of course, the lawnmover that it is, I have no
    way to know by now.

    Of course, we can simply #define a buggy compiler as non-conformant, but
    how does that help people running our code? Especially if they build it
    at home, and have no idea what's happening, or why it's not working?

    But since this is not a group about executable binaries, I'll leave it
    at that.


    Happy finding compiler bugs! How many did you find?
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Johann 'Myrkraverk' Oskarsson@3:633/10 to All on Sat Aug 22 00:31:40 2026
    On 20/08/2026 10:53 PM, Scott Lurndal wrote:
    Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
    Lawrence D?Oliveiro <ldo@nz.invalid> writes:
    On Wed, 19 Aug 2026 12:21:15 -0000 (UTC), Richard Tobin wrote:
    In the early days of C, this was often so, and some programs wrongly
    depended on it. In some of those cases the mistake became apparent
    when shared libraries were introduced, because of the dynamic linker
    running before main().

    I still don?t understand the connection with dynamic linking.

    Oh? I thought it had been explained clearly enough, several times.

    The idea is that dynamic linking introduced the possibility of
    initialization code from dynamic libraries being invoked before
    main() is called. I've already explained how this can clobber the
    memory that's used for local variables when main() runs.

    Without dynamic linking, main() is the first code that runs when
    the program is executed. It allocates its local variables in memory
    that's been zeroed by the OS.

    Even without dynamic linking, the CRT (C Run-time) code will execute
    before main() (often at a symbol called _start). I don't recall
    any guarantee that the CRT code won't use the stack prior to invoking main.

    You did not thump the standard hard enough, Scott Lurndal. It's
    perfectly valid implementation to include in the main() prologue the
    call to initialize the the /C runtime environment/. Of course, you get
    into a minor conundrum about argc and argv, but that's easily resolved
    by defining your implementation to use signed main( void ) instead of
    the normal

    int main( int argc, char *argv[] ) ;

    but that's a digression. Anyway, just create your own compiler with
    the main() prologue as

    int main( int argc, char *argv[] ) {
    __my_init_crt() ;
    argc = __something ; argv = __something_else ;

    // ...
    return 0 ;
    }

    and move on with your life.


    Happy compiler making!
    --
    Johann | email: invalid -> com | http://www.myrkraverk.com/blog/
    I'm not from the Internet, I just work there. | via Easynews.com https://bsky.app/profile/myrkraverk.bsky.social | for ( ;; ) _:;

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Fri Aug 21 12:20:51 2026
    On 8/21/2026 12:22 AM, David Brown wrote:
    On 20/08/2026 21:26, Chris M. Thomasson wrote:
    On 8/20/2026 4:53 AM, Kenny McCormack wrote:
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brownÿ <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this thread!) >>>
    Heh heh.ÿ Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it
    seemed odd
    that it worked (*).ÿ Unless it was actually part of the language, as
    it now
    seems it is.

    (*) Worked in the sense that it was always 0.ÿ Not that the code was
    relying on that, of course.


    simply never assume that a in say:

    int a;

    equals zero. Its fairly simple.

    That only applies to non-static local variables.ÿ Program lifetime data
    is always initialised.ÿ Code can happily rely on initialisation
    happening as required by the rules of the C language.


    Shit. Well, still, I have a habit of trying to initialize everything.
    So, yes, I tend to write:

    static int g_a = 0;

    Shit happens.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Lawrence D?Oliveiro@3:633/10 to All on Sat Aug 22 05:55:01 2026
    On Fri, 21 Aug 2026 12:20:51 -0700, Chris M. Thomasson wrote:

    Shit. Well, still, I have a habit of trying to initialize
    everything. So, yes, I tend to write:

    static int g_a = 0;

    I would say there is no harm in that. Shouldn?t any difference to
    generated code.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From David Brown@3:633/10 to All on Sat Aug 22 13:29:42 2026
    On 21/08/2026 21:20, Chris M. Thomasson wrote:
    On 8/21/2026 12:22 AM, David Brown wrote:
    On 20/08/2026 21:26, Chris M. Thomasson wrote:
    On 8/20/2026 4:53 AM, Kenny McCormack wrote:
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brownÿ <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been
    totally ruined by your clear, topical C question starting this
    thread!)

    Heh heh.ÿ Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it
    seemed odd
    that it worked (*).ÿ Unless it was actually part of the language, as
    it now
    seems it is.

    (*) Worked in the sense that it was always 0.ÿ Not that the code was
    relying on that, of course.


    simply never assume that a in say:

    int a;

    equals zero. Its fairly simple.

    That only applies to non-static local variables.ÿ Program lifetime
    data is always initialised.ÿ Code can happily rely on initialisation
    happening as required by the rules of the C language.


    Shit. Well, still, I have a habit of trying to initialize everything.
    So, yes, I tend to write:

    static int g_a = 0;

    Write that if you like - and if it makes code clearer, it can be a good
    thing. It is unlikely to be helpful to the reader to have an explicit
    "0" initialiser, but it certainly could be if it is an enumeration
    value, constexpr value, macro, or something else that is not obviously 0.

    Contrary to Lawrence's answer, it typically /will/ make a difference to generated code - just one that is completely negligible in all but the smallest of embedded systems. In most of the toolchains I have used,
    "static int g;" goes in the ".bss" segment and gets zeroed as part of a
    loop, while "static int g = 0;" goes in the ".data" segment and is
    initialised by copying from a read-only segment of the executable. Thus
    the explicit initialisation is marginally less efficient.

    On the other hand, there are a few embedded toolchains (primarily those provided by Texas Instruments) which do not zero-initialise program
    lifetime data that has no explicit initialisation - they do not clear
    the ".bss" and "static int g;" variables before main(). The misguided
    fools at TI call this a "feature" leading to faster startup - users call
    it a painful and deceptive flaw and non-conformity which has lead to
    countless problems and wasted debugging time. It has also lead some
    providers of portable embedded code to use explicit initialisation to 0
    as you have done, giving less efficient code on platforms with more
    conforming tools.


    Shit happens.

    I get the impression that you don't understand what that phrase means.
    You should stop using it - it makes no sense in the contexts you write it.



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Sat Aug 22 14:16:01 2026
    On 8/22/2026 4:29 AM, David Brown wrote:
    On 21/08/2026 21:20, Chris M. Thomasson wrote:
    On 8/21/2026 12:22 AM, David Brown wrote:
    On 20/08/2026 21:26, Chris M. Thomasson wrote:
    On 8/20/2026 4:53 AM, Kenny McCormack wrote:
    In article <1166ost$3dg4d$1@dont-email.me>,
    David Brownÿ <david.brown@hesbynett.no> wrote:
    ...
    (It's nice to see that your reputation as group cynic has not been >>>>>> totally ruined by your clear, topical C question starting this
    thread!)

    Heh heh.ÿ Well, somebody's got to do it.

    This actually came up in real code that I was working on, and it
    seemed odd
    that it worked (*).ÿ Unless it was actually part of the language,
    as it now
    seems it is.

    (*) Worked in the sense that it was always 0.ÿ Not that the code was >>>>> relying on that, of course.


    simply never assume that a in say:

    int a;

    equals zero. Its fairly simple.

    That only applies to non-static local variables.ÿ Program lifetime
    data is always initialised.ÿ Code can happily rely on initialisation
    happening as required by the rules of the C language.


    Shit. Well, still, I have a habit of trying to initialize everything.
    So, yes, I tend to write:

    static int g_a = 0;

    Write that if you like - and if it makes code clearer, it can be a good thing.ÿ It is unlikely to be helpful to the reader to have an explicit
    "0" initialiser, but it certainly could be if it is an enumeration
    value, constexpr value, macro, or something else that is not obviously 0.

    Contrary to Lawrence's answer, it typically /will/ make a difference to generated code - just one that is completely negligible in all but the smallest of embedded systems.ÿ In most of the toolchains I have used, "static int g;" goes in the ".bss" segment and gets zeroed as part of a loop, while "static int g = 0;" goes in the ".data" segment and is initialised by copying from a read-only segment of the executable.ÿ Thus
    the explicit initialisation is marginally less efficient.


    On the other hand, there are a few embedded toolchains (primarily those provided by Texas Instruments) which do not zero-initialise program
    lifetime data that has no explicit initialisation - they do not clear
    the ".bss" and "static int g;" variables before main().ÿ The misguided
    fools at TI call this a "feature" leading to faster startup - users call
    it a painful and deceptive flaw and non-conformity which has lead to countless problems and wasted debugging time.ÿ It has also lead some providers of portable embedded code to use explicit initialisation to 0
    as you have done, giving less efficient code on platforms with more conforming tools.


    Shit happens.

    Indeed. It's just a habit I got into several decades ago.


    I get the impression that you don't understand what that phrase means.
    You should stop using it - it makes no sense in the contexts you write it.


    :^) I wrote that because according to C std, I never needed to get into
    the habit of:

    static int g_a = 0;

    I could have left it as:

    static int g_a;

    sigh... So as the phrase goes.

    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Chris M. Thomasson@3:633/10 to All on Sat Aug 22 14:17:57 2026
    On 8/22/2026 4:29 AM, David Brown wrote:
    [...]

    Fwiw, the last os used for embedded things I used was Quadros.


    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)
  • From Michael S@3:633/10 to All on Sun Aug 23 01:23:30 2026
    On Sat, 22 Aug 2026 13:29:42 +0200
    David Brown <david.brown@hesbynett.no> wrote:

    On 21/08/2026 21:20, Chris M. Thomasson wrote:


    Shit happens.

    I get the impression that you don't understand what that phrase
    means. You should stop using it - it makes no sense in the contexts
    you write it.



    A cornerstone of existentialism?



    --- PyGate Linux v1.5.19
    * Origin: Dragon's Lair, PyGate NNTP<>Fido Gate (3:633/10)