Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #390224 > unrolled thread

Two questions on arrays with size defined by variables

Started byJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
First post2025-02-09 08:50 +0100
Last post2025-02-15 08:19 -0800
Articles 20 on this page of 45 — 9 participants

Back to article view | Back to comp.lang.c


Contents

  Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 08:50 +0100
    Re: Two questions on arrays with size defined by variables Andrey Tarasevich <noone@noone.net> - 2025-02-09 00:06 -0800
      Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 10:54 +0100
        Re: Two questions on arrays with size defined by variables Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-02-09 02:25 -0800
          Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 18:17 +0100
            Re: Two questions on arrays with size defined by variables Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-02-09 16:38 -0800
              Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 03:35 +0100
                Re: Two questions on arrays with size defined by variables James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-02-09 23:03 -0500
                Re: Two questions on arrays with size defined by variables Andrey Tarasevich <noone@noone.net> - 2025-02-09 20:14 -0800
                  Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 07:43 +0100
                    Re: Two questions on arrays with size defined by variables Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-02-09 22:57 -0800
                      Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 19:33 +0100
                        Re: Two questions on arrays with size defined by variables Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-02-10 14:17 -0800
        Re: Two questions on arrays with size defined by variables Michael S <already5chosen@yahoo.com> - 2025-02-09 12:39 +0200
          Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 18:18 +0100
            Re: Two questions on arrays with size defined by variables Michael S <already5chosen@yahoo.com> - 2025-02-09 19:57 +0200
              Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 19:10 +0100
              Re: Two questions on arrays with size defined by variables Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-02-09 16:46 -0800
                Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 02:56 +0100
        Re: Two questions on arrays with size defined by variables antispam@fricas.org (Waldek Hebisch) - 2025-02-09 14:29 +0000
          Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 18:19 +0100
            Re: Two questions on arrays with size defined by variables Andrey Tarasevich <noone@noone.net> - 2025-02-09 09:29 -0800
              Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 18:46 +0100
                Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 18:53 +0100
                  Re: Two questions on arrays with size defined by variables James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-02-09 15:55 -0500
                    Re: Two questions on arrays with size defined by variables antispam@fricas.org (Waldek Hebisch) - 2025-02-10 01:36 +0000
                    Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 03:01 +0100
                      Re: Two questions on arrays with size defined by variables David Brown <david.brown@hesbynett.no> - 2025-02-10 11:39 +0100
                        Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 18:57 +0100
                          Re: Two questions on arrays with size defined by variables David Brown <david.brown@hesbynett.no> - 2025-02-10 19:19 +0100
                Re: Two questions on arrays with size defined by variables Michael S <already5chosen@yahoo.com> - 2025-02-09 20:19 +0200
                  Re: Two questions on arrays with size defined by variables Opus <ifonly@youknew.org> - 2025-02-10 02:44 +0100
                    Re: Two questions on arrays with size defined by variables Michael S <already5chosen@yahoo.com> - 2025-02-10 12:38 +0200
                      Re: Two questions on arrays with size defined by variables Opus <ifonly@youknew.org> - 2025-02-10 23:08 +0100
            Re: Two questions on arrays with size defined by variables Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-02-09 15:50 -0800
              Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 03:12 +0100
                Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 07:27 +0100
                  Re: Two questions on arrays with size defined by variables Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-02-09 22:49 -0800
                    Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-10 19:14 +0100
        Re: Two questions on arrays with size defined by variables Andrey Tarasevich <noone@noone.net> - 2025-02-09 07:15 -0800
          Re: Two questions on arrays with size defined by variables Janis Papanagnou <janis_papanagnou+ng@hotmail.com> - 2025-02-09 18:20 +0100
          Re: Two questions on arrays with size defined by variables James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-02-09 15:34 -0500
        Re: Two questions on arrays with size defined by variables James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-02-09 15:27 -0500
      Re: Two questions on arrays with size defined by variables James Kuyper <jameskuyper@alumni.caltech.edu> - 2025-02-09 15:16 -0500
      Re: Two questions on arrays with size defined by variables Tim Rentsch <tr.17687@z991.linuxsc.com> - 2025-02-15 08:19 -0800

Page 1 of 3  [1] 2 3  Next page →


#390224 — Two questions on arrays with size defined by variables

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-09 08:50 +0100
SubjectTwo questions on arrays with size defined by variables
Message-ID<vo9mns$gsd7$1@dont-email.me>
I need an array whose size is depending on values that are dynamically
determined by the program. (I suppose those are the "VLAs" that I've
read about here occasionally? - Anyway, however they're named...)

I've found examples on the Net where the arrays have been defined in a
function context and the size passed as parameter

  f(int n) {
     char * arr[n];
     ...
  }

That reminded me on other languages where you'd need at least a block
context for dynamically sized arrays, like

  int n = 5;
  {
     char * arr[n];
     ...
  }

Anyway. I tried it without function or block context

  int n = 5;
  char * arr[n];
  ...

and it seemed to work seamlessly like that (with GNU cc, -std=C99).

Q1: Is this a correct (portable) form?


Then, with above setting, I also tried

  arr[99] = "foobar";

To my astonishment the compiler did not only accept that but it also
operated without runtime error; but I assume it's an error that may
severely corrupt the memory. - Q2: Is my suspicion correct?

Janis

[toc] | [next] | [standalone]


#390225

FromAndrey Tarasevich <noone@noone.net>
Date2025-02-09 00:06 -0800
Message-ID<vo9nn3$gtph$1@dont-email.me>
In reply to#390224
On Sat 2/8/2025 11:50 PM, Janis Papanagnou wrote:
> I've found examples on the Net where the arrays have been defined in a
> function context and the size passed as parameter
> 
>    f(int n) {
>       char * arr[n];
>       ...
>    }

Yes, that would be a VLA.

> That reminded me on other languages where you'd need at least a block
> context for dynamically sized arrays, like
> 
>    int n = 5;
>    {
>       char * arr[n];
>       ...
>    }

But a function body is in itself a block. Inside a function body you are 
already in "a block context".

> Anyway. I tried it without function or block context
> 
>    int n = 5;
>    char * arr[n];
>    ...
> 
> and it seemed to work seamlessly like that (with GNU cc, -std=C99).

You mean you did this at file scope? No, VLAs are illegal at file scope. 
And I was unable to repeat this feat in GCC.

> Q1: Is this a correct (portable) form?

VLA objects have to be declared locally. However, keep in mind that 
support for local declarations of VLA _objects_ is now optional (i.e. 
not portable). Support for variably-modified _types_ themselves (VLA 
types) is mandatory. But you are not guaranteed to be able to declare an 
actual VLA variable.

> Then, with above setting, I also tried
> 
>    arr[99] = "foobar";
> 
> To my astonishment the compiler did not only accept that but it also
> operated without runtime error; but I assume it's an error that may
> severely corrupt the memory. - Q2: Is my suspicion correct?

Yes. Since the beginning of times the language itself does not 
check/enforce array boundaries. When you violate the boundary, the 
behavior is undefined, meaning that compilers can do anything (including 
implementing array boundary checks, where possible). But for obvious 
performance reasons C compilers do not normally enforce array boundaries 
in "production" compilation modes.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#390226

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-09 10:54 +0100
Message-ID<vo9u0u$i0n8$1@dont-email.me>
In reply to#390225
On 09.02.2025 09:06, Andrey Tarasevich wrote:
> On Sat 2/8/2025 11:50 PM, Janis Papanagnou wrote:
>> I've found examples on the Net where the arrays have been defined in a
>> function context and the size passed as parameter
>>
>>    f(int n) {
>>       char * arr[n];
>>       ...
>>    }
> 
> Yes, that would be a VLA.
> 
>> That reminded me on other languages where you'd need at least a block
>> context for dynamically sized arrays, like
>>
>>    int n = 5;
>>    {
>>       char * arr[n];
>>       ...
>>    }
> 
> But a function body is in itself a block. Inside a function body you are
> already in "a block context".
> 
>> Anyway. I tried it without function or block context
>>
>>    int n = 5;
>>    char * arr[n];
>>    ...
>>
>> and it seemed to work seamlessly like that (with GNU cc, -std=C99).
> 
> You mean you did this at file scope? No, VLAs are illegal at file scope.
> And I was unable to repeat this feat in GCC.

Oh, sorry, no; above I had just written an excerpt. - Actually I had
those two examples above within a main() function. - Sorry again for
my inaccuracy.

What I meant was (with surrounding context) that I knew (from _other_
languages) a syntax like

main ()
{
  int n = 5;

  {
     char * arr[n];
     ...
  }
}

And in "C" (C99) I tried it *without* the _inner block_

main ()
{
  int n = 5;
  char * arr[n];
  ...
}

and it seemed to work that way. (In those other languages that wasn't
possible.)

> 
>> Q1: Is this a correct (portable) form?
> 
> VLA objects have to be declared locally. However, keep in mind that
> support for local declarations of VLA _objects_ is now optional (i.e.
> not portable). Support for variably-modified _types_ themselves (VLA
> types) is mandatory. But you are not guaranteed to be able to declare an
> actual VLA variable.

I fear I don't understand what you're saying here. - By "now" do you
mean newer versions of the C standards? That you can rely only, say,
rely on it with C99 but maybe not before and not in later C standards
conforming compilers?

For my purpose it would be okay to know whether with the C99 version
(that I used) it's okay, or whether that's some GNU specific extension
or some such.

Janis

> 
>> [...]

[toc] | [prev] | [next] | [standalone]


#390227

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-02-09 02:25 -0800
Message-ID<878qqf1kl2.fsf@nosuchdomain.example.com>
In reply to#390226
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
> On 09.02.2025 09:06, Andrey Tarasevich wrote:
>> On Sat 2/8/2025 11:50 PM, Janis Papanagnou wrote:
>>> I've found examples on the Net where the arrays have been defined in a
>>> function context and the size passed as parameter
>>>
>>>    f(int n) {
>>>       char * arr[n];
>>>       ...
>>>    }
>> 
>> Yes, that would be a VLA.
>> 
>>> That reminded me on other languages where you'd need at least a block
>>> context for dynamically sized arrays, like
>>>
>>>    int n = 5;
>>>    {
>>>       char * arr[n];
>>>       ...
>>>    }
>> 
>> But a function body is in itself a block. Inside a function body you are
>> already in "a block context".
>> 
>>> Anyway. I tried it without function or block context
>>>
>>>    int n = 5;
>>>    char * arr[n];
>>>    ...
>>>
>>> and it seemed to work seamlessly like that (with GNU cc, -std=C99).
>> 
>> You mean you did this at file scope? No, VLAs are illegal at file scope.
>> And I was unable to repeat this feat in GCC.
>
> Oh, sorry, no; above I had just written an excerpt. - Actually I had
> those two examples above within a main() function. - Sorry again for
> my inaccuracy.
>
> What I meant was (with surrounding context) that I knew (from _other_
> languages) a syntax like
>
> main ()
> {
>   int n = 5;
>
>   {
>      char * arr[n];
>      ...
>   }
> }
>
> And in "C" (C99) I tried it *without* the _inner block_
>
> main ()
> {
>   int n = 5;
>   char * arr[n];
>   ...
> }

The first line needs to be `int main(void)`.  The "implicit int"
misfeature was removed in C99.  Your compiler might let you get away
with it; many C compilers are quite lax by default.  For gcc, use
"-std=cNN -pedantic" to enforce the language rules, where NN specifies
the language version.

> and it seemed to work that way. (In those other languages that wasn't
> possible.)

VLAs were introduced in C99, so the above is invalid in C90 with or
without the inner block.  In C99 and later, there's no requirement to
put the VLA object definition in an inner block (if the implementation
supports them).  (C99 did add the ability to mix declarations and
statements, but that's not relevant to your example).

>>> Q1: Is this a correct (portable) form?
>> 
>> VLA objects have to be declared locally. However, keep in mind that
>> support for local declarations of VLA _objects_ is now optional (i.e.
>> not portable). Support for variably-modified _types_ themselves (VLA
>> types) is mandatory. But you are not guaranteed to be able to declare an
>> actual VLA variable.
>
> I fear I don't understand what you're saying here. - By "now" do you
> mean newer versions of the C standards? That you can rely only, say,
> rely on it with C99 but maybe not before and not in later C standards
> conforming compilers?

C90 didn't have VLAs at all.

C99 introduced them and required all implementations to support them.

C11 made variably modified types optional.

C23 still makes variable length arrays with automatic storage duration
optional but "Parameters declared with variable length array types are
adjusted and then define objects of automatic storage duration with
pointer types. Thus, support for such declarations is mandatory."
(Support for C23 is still preliminary.)

> For my purpose it would be okay to know whether with the C99 version
> (that I used) it's okay, or whether that's some GNU specific extension
> or some such.

C99 requires support for local objects of variable length array types.

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

[toc] | [prev] | [next] | [standalone]


#390234

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-09 18:17 +0100
Message-ID<voanvq$o6uh$1@dont-email.me>
In reply to#390227
On 09.02.2025 11:25, Keith Thompson wrote:
> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>> On 09.02.2025 09:06, Andrey Tarasevich wrote:
[...]
>>> But a function body is in itself a block. Inside a function body you are
>>> already in "a block context".
>>>
>>>> Anyway. I tried it without function or block context
>>>>
>>>>    int n = 5;
>>>>    char * arr[n];
>>>>    ...
>>>>
>>>> and it seemed to work seamlessly like that (with GNU cc, -std=C99).
>>>
>>> You mean you did this at file scope? No, VLAs are illegal at file scope.
>>> And I was unable to repeat this feat in GCC.
>>
>> Oh, sorry, no; above I had just written an excerpt. - Actually I had
>> those two examples above within a main() function. - Sorry again for
>> my inaccuracy.
>>
>> What I meant was (with surrounding context) that I knew (from _other_
>> languages) a syntax like
>>
>> main ()
>> {
>>   int n = 5;
>>
>>   {
>>      char * arr[n];
>>      ...
>>   }
>> }
>>
>> And in "C" (C99) I tried it *without* the _inner block_
>>
>> main ()
>> {
>>   int n = 5;
>>   char * arr[n];
>>   ...
>> }
> 
> The first line needs to be `int main(void)`.  The "implicit int"
> misfeature was removed in C99. [...]

Thanks. (Again answering more/something different than I asked.) :-)

Please note that I structurally illustrated just the posters question
about where the relevant code excerpt resides (file scope or else).

If I'd knew the audience is picky I'd posted the whole test program;
but then there's even much more picky comments to expect. ;-)

I hope to mollify the audience if I point out that my code actually
looks *like* this

  ...
  int main (int argc, char * argv[])
  {
      ...
      return 0;
  }

(And, yes, I know that the "..." is not correct, and argc is unused,
and I omitted 'const', etc.)

> [...] but that's not relevant to your example).

Right.

> 
>> [...]
> 
> C90 didn't have VLAs at all.
> 
> C99 introduced them and required all implementations to support them.
> 
> C11 made variably modified types optional.
> 
> C23 still makes variable length arrays with automatic storage duration
> optional but "Parameters declared with variable length array types are
> adjusted and then define objects of automatic storage duration with
> pointer types. Thus, support for such declarations is mandatory."
> (Support for C23 is still preliminary.)
> 
>> For my purpose it would be okay to know whether with the C99 version
>> (that I used) it's okay, or whether that's some GNU specific extension
>> or some such.
> 
> C99 requires support for local objects of variable length array types.

Thanks!

Janis

[toc] | [prev] | [next] | [standalone]


#390254

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-02-09 16:38 -0800
Message-ID<877c5yr5vv.fsf@nosuchdomain.example.com>
In reply to#390234
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
> On 09.02.2025 11:25, Keith Thompson wrote:
[...]
>> The first line needs to be `int main(void)`.  The "implicit int"
>> misfeature was removed in C99. [...]
>
> Thanks. (Again answering more/something different than I asked.) :-)
>
> Please note that I structurally illustrated just the posters question
> about where the relevant code excerpt resides (file scope or else).
>
> If I'd knew the audience is picky I'd posted the whole test program;
> but then there's even much more picky comments to expect. ;-)

Yeah, we're picky here.

> I hope to mollify the audience if I point out that my code actually
> looks *like* this
>
>   ...
>   int main (int argc, char * argv[])
>   {
>       ...
>       return 0;
>   }
>
> (And, yes, I know that the "..." is not correct, and argc is unused,
> and I omitted 'const', etc.)

It's clear enough that the "..." is figurative.  As picky as I am,
I wouldn't have commented on it.  "// ..." or "/* ... */" is more
pedantically correct, but whatever.

(Incidentally, Perl has a "..." operator, nicknamed the Yada Yada
operator, intended to mark placeholder code that is not yet
implemented.)

The "return 0;" is unnecessary but harmless in C99 and later.

As for "const", there's nothing in the above snippet that requires it.
You can probably add a const or two to the argv declaration:
    const char *const *argv
but the standard doesn't include "const" in the declaration of argv.
Strictly speaking, adding "const" probably makes the program's behavior
undefined.

[...]

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

[toc] | [prev] | [next] | [standalone]


#390268

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-10 03:35 +0100
Message-ID<vobol8$ts5l$1@dont-email.me>
In reply to#390254
On 10.02.2025 01:38, Keith Thompson wrote:
> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>>
>> If I'd knew the audience is picky I'd posted the whole test program;
>> but then there's even much more picky comments to expect. ;-)
> 
> Yeah, we're picky here.
> 
>> I hope to mollify the audience if I point out that my code actually
>> looks *like* this
>>
>>   ...
>>   int main (int argc, char * argv[])
>>   {
>>       ...
>>       return 0;
>>   }
>>
>> (And, yes, I know that the "..." is not correct, and argc is unused,
>> and I omitted 'const', etc.)
> 
> It's clear enough that the "..." is figurative. 

And my  main() { ... }  was to figuratively illustrate the structure.

I could have also used  f() { ... }  but it didn't occur to me that
using main would trigger yet another off-topic comment.

> As picky as I am, I wouldn't have commented on it. 

Some are more picky some less, some on this detail others on that.

I think we're all well served if we'd be more equanimous especially
when postings or clarifying things are based on _excerpts_ or code
snippets.

I know that specifically in _this_ newsgroup that is difficult. :-)

> "// ..." or "/* ... */" is more
> pedantically correct, but whatever.

But this is code. The meta '...' is clearly descriptive for some
[contextually uninteresting] things omitted.

(You see what I mean by trying to be more equanimous. Perception
of folks differs a lot. We cannot expect others to share our views
or habits.)

> 
> (Incidentally, Perl has a "..." operator, nicknamed the Yada Yada
> operator, intended to mark placeholder code that is not yet
> implemented.)
> 
> The "return 0;" is unnecessary but harmless in C99 and later.

That - returning a value when a function is declared to return
one - is actually a [maybe picky] coding-habit of mine. :-)

Janis

[toc] | [prev] | [next] | [standalone]


#390270

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2025-02-09 23:03 -0500
Message-ID<vobtr8$12bhh$1@dont-email.me>
In reply to#390268
On 2/9/25 21:35, Janis Papanagnou wrote:
> On 10.02.2025 01:38, Keith Thompson wrote:
>> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
...
>>> int main (int argc, char * argv[])
>>> {
>>> ...
>>> return 0;
>>> }
...
>> The "return 0;" is unnecessary but harmless in C99 and later.
>
> That - returning a value when a function is declared to return
> one - is actually a [maybe picky] coding-habit of mine. :-)

It's a reasonable habit to acquire. However, the interface for main()
was created back when there was no way to declare that a function didn't
return any value, and all functions by default returned "int" unless
explicitly declared otherwise. It made sense, therefore, for main() to
be declared as returning an int value that would be passed to the host
environment to indicate the exit status of the program.
Many programmers had no need to report an exit status, and therefore
didn't bother returning a value from main(). As a result, many
implementations failed to require it. Eventually the committee decided
to make a special case for main(), to accommodate those practices.

[toc] | [prev] | [next] | [standalone]


#390272

FromAndrey Tarasevich <noone@noone.net>
Date2025-02-09 20:14 -0800
Message-ID<vobuea$12bi8$2@dont-email.me>
In reply to#390268
On Sun 2/9/2025 6:35 PM, Janis Papanagnou wrote:
>> The "return 0;" is unnecessary but harmless in C99 and later.
> 
> That - returning a value when a function is declared to return
> one - is actually a [maybe picky] coding-habit of mine. :-)

This is, of course, a purely stylistic matter. But still... `main` is 
special. And it kinda makes sense to acknowledge it special nature by 
not doing explicit `return 0` from `main`. `main` looks cleaner without it.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#390277

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-10 07:43 +0100
Message-ID<voc76f$13jns$1@dont-email.me>
In reply to#390272
On 10.02.2025 05:14, Andrey Tarasevich wrote:
> On Sun 2/9/2025 6:35 PM, Janis Papanagnou wrote:
>>> The "return 0;" is unnecessary but harmless in C99 and later.
>>
>> That - returning a value when a function is declared to return
>> one - is actually a [maybe picky] coding-habit of mine. :-)
> 
> This is, of course, a purely stylistic matter. But still... `main` is
> special.

I know.

> And it kinda makes sense to acknowledge it special nature by
> not doing explicit `return 0` from `main`. `main` looks cleaner without it.

Now I'm astonished by that comment (to say the least).

I'm regularly returning status and error information to the calling
instance to act upon it. And you're saying that I should not return
any value? Or only values that are different from 0? Or only 0 if I
also return other values? - Whatever; that sounds all wrong to me.
Or is 'return' deprecated or depreciated and we should now rewrite
our source code and replace every 'return' by 'exit()', or use now
only 'exit()' in the first place instead?

I don't think you will convince me to not return 0 only because in
the special case that there's nothing specified the current language
standards defines that per default it implicitly provides that value
for me.

Janis

[toc] | [prev] | [next] | [standalone]


#390280

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-02-09 22:57 -0800
Message-ID<878qqep9rx.fsf@nosuchdomain.example.com>
In reply to#390277
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
> On 10.02.2025 05:14, Andrey Tarasevich wrote:
>> On Sun 2/9/2025 6:35 PM, Janis Papanagnou wrote:
>>>> The "return 0;" is unnecessary but harmless in C99 and later.
>>>
>>> That - returning a value when a function is declared to return
>>> one - is actually a [maybe picky] coding-habit of mine. :-)
>> 
>> This is, of course, a purely stylistic matter. But still... `main` is
>> special.
>
> I know.
>
>> And it kinda makes sense to acknowledge it special nature by
>> not doing explicit `return 0` from `main`. `main` looks cleaner without it.
>
> Now I'm astonished by that comment (to say the least).
>
> I'm regularly returning status and error information to the calling
> instance to act upon it. And you're saying that I should not return
> any value? Or only values that are different from 0? Or only 0 if I
> also return other values? - Whatever; that sounds all wrong to me.
> Or is 'return' deprecated or depreciated and we should now rewrite
> our source code and replace every 'return' by 'exit()', or use now
> only 'exit()' in the first place instead?
>
> I don't think you will convince me to not return 0 only because in
> the special case that there's nothing specified the current language
> standards defines that per default it implicitly provides that value
> for me.

Having a "return 0;" at the end of main() is neither obsolescent nor
deprecated.  It's still perfectly valid, with the expected semantics.

The only that changed in C99 is that reaching the closing "}" of
the main function does an implicit "return 0;".  This change was
borrowed from C++.

I do tend to dislike the change; it feels like an unnecessary special
case, and I used to advise people to add an explicit "return 0;"
anyway.  This was partly because C99 compilers were relatively rare,
and there were advantages to writing code that still worked with
C90-only compilers.

I usually omit the "return 0;", but I don't object to including it --
though I will occasionally mention in passing that it's "unnecessary
but harmless".  If nothing else, the history is interesting (at
least to me).

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

[toc] | [prev] | [next] | [standalone]


#390289

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-10 19:33 +0100
Message-ID<vodgqk$1b1u0$1@dont-email.me>
In reply to#390280
On 10.02.2025 07:57, Keith Thompson wrote:
> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
>> [...]
> 
> Having a "return 0;" at the end of main() is neither obsolescent nor
> deprecated.  It's still perfectly valid, with the expected semantics.
> 
> The only that changed in C99 is that reaching the closing "}" of
> the main function does an implicit "return 0;".  This change was
> borrowed from C++.
> 
> I do tend to dislike the change; it feels like an unnecessary special
> case, and I used to advise people to add an explicit "return 0;"
> anyway.  This was partly because C99 compilers were relatively rare,
> and there were advantages to writing code that still worked with
> C90-only compilers.
> 
> I usually omit the "return 0;", but I don't object to including it --
> though I will occasionally mention in passing that it's "unnecessary
> but harmless".  If nothing else, the history is interesting (at
> least to me).

I'm with you.

Personally I think it's an uninteresting point; primarily because
it's a detail and, as you wrote, also a special case.

I would prefer - but for that reason of minor importance to me I
also don't mind as it is - if the language would allow all sorts
of interface variants, e.g.

  void main (void) { ... }    or also    void main () { ... }
  int main (void) { ... ; return rc; }

  void main (int argc, ...) { ... }
  int main (int argc, ...) { ... ; return rc; }

if they are _consistent_; i.e. no 'return' allowed in case of a
void declaration (with an implicit return 0 to the environment),
and requiring an explicit 'return' in case of an int declaration.

What I find bad is if some special [visibly inconsistent] form
is the norm and other [more consistent] forms are "UB" with the
"threat" of the proverbial missile launch as possible outcome.

I haven't checked what's actually valid in current or former
"C" compilers or standards. As it's of minor relevance (to me)
I just see whether the compiler accepts my main() declaration
or not. (There was never a problem here, so why should I care.)

Janis

[toc] | [prev] | [next] | [standalone]


#390293

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-02-10 14:17 -0800
Message-ID<87zfito36l.fsf@nosuchdomain.example.com>
In reply to#390289
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> writes:
[...]
> I haven't checked what's actually valid in current or former
> "C" compilers or standards. As it's of minor relevance (to me)
> I just see whether the compiler accepts my main() declaration
> or not. (There was never a problem here, so why should I care.)

That was probably meant to be a rhetorical question, but ...

Because it might not always work in the future, when you port your
code to another system, when a new release of the compiler you're
using is installed, or during the next full moon.  If your code
has undefined behavior, it might appear to work perfectly until
it doesn't.

If your code is valid according to the C standard, you're less likely to
run into problems -- and if a compiler rejects your code you have a good
basis for a bug report.  If "void main()" or "main()" starts behaving
differently, or being rejected, you don't have much recourse.

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

[toc] | [prev] | [next] | [standalone]


#390228

FromMichael S <already5chosen@yahoo.com>
Date2025-02-09 12:39 +0200
Message-ID<20250209123918.0000754f@yahoo.com>
In reply to#390226
On Sun, 9 Feb 2025 10:54:36 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

> On 09.02.2025 09:06, Andrey Tarasevich wrote:
> > On Sat 2/8/2025 11:50 PM, Janis Papanagnou wrote:  
> >> I've found examples on the Net where the arrays have been defined
> >> in a function context and the size passed as parameter
> >>
> >>    f(int n) {
> >>       char * arr[n];
> >>       ...
> >>    }  
> > 
> > Yes, that would be a VLA.
> >   
> >> That reminded me on other languages where you'd need at least a
> >> block context for dynamically sized arrays, like
> >>
> >>    int n = 5;
> >>    {
> >>       char * arr[n];
> >>       ...
> >>    }  
> > 
> > But a function body is in itself a block. Inside a function body
> > you are already in "a block context".
> >   
> >> Anyway. I tried it without function or block context
> >>
> >>    int n = 5;
> >>    char * arr[n];
> >>    ...
> >>
> >> and it seemed to work seamlessly like that (with GNU cc,
> >> -std=C99).  
> > 
> > You mean you did this at file scope? No, VLAs are illegal at file
> > scope. And I was unable to repeat this feat in GCC.  
> 
> Oh, sorry, no; above I had just written an excerpt. - Actually I had
> those two examples above within a main() function. - Sorry again for
> my inaccuracy.
> 
> What I meant was (with surrounding context) that I knew (from _other_
> languages) a syntax like
> 
> main ()
> {
>   int n = 5;
> 
>   {
>      char * arr[n];
>      ...
>   }
> }
> 
> And in "C" (C99) I tried it *without* the _inner block_
> 
> main ()
> {
>   int n = 5;
>   char * arr[n];
>   ...
> }
> 
> and it seemed to work that way. (In those other languages that wasn't
> possible.)
> 
> >   
> >> Q1: Is this a correct (portable) form?  
> > 
> > VLA objects have to be declared locally. However, keep in mind that
> > support for local declarations of VLA _objects_ is now optional
> > (i.e. not portable). Support for variably-modified _types_
> > themselves (VLA types) is mandatory. But you are not guaranteed to
> > be able to declare an actual VLA variable.  
> 
> I fear I don't understand what you're saying here. - By "now" do you
> mean newer versions of the C standards? That you can rely only, say,
> rely on it with C99 but maybe not before and not in later C standards
> conforming compilers?
>

Yes, theoretically.
In practice, I am not sure that there exists fully conforming C17 or
especially C23 compiler that does not support VLA. But there exists one
important almost-C17 compiler that does not support VLA.

There is another problem in your code - it assigns string literal to
non-const char*. It is legal, as far as 'C' Standard is concerned, but
makes very little practical sense, because any attempt to assign to
string literal through resulting pointer is UB. And not just a
theoretical UB, but a real-world UB.

> For my purpose it would be okay to know whether with the C99 version
> (that I used) it's okay, or whether that's some GNU specific extension
> or some such.
> 
> Janis
> 
> >   
> >> [...]  
> 
>

[toc] | [prev] | [next] | [standalone]


#390235

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-09 18:18 +0100
Message-ID<voao0d$o71o$1@dont-email.me>
In reply to#390228
On 09.02.2025 11:39, Michael S wrote:
> On Sun, 9 Feb 2025 10:54:36 +0100
> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
> [...]
> 
> There is another problem in your code - it assigns string literal to
> non-const char*. It is legal, as far as 'C' Standard is concerned, but
> makes very little practical sense, because any attempt to assign to
> string literal through resulting pointer is UB. And not just a
> theoretical UB, but a real-world UB.

This comment specifically draw my attention and made me nervous.

You know, I'm rarely programming in plain "C", and while in C++
I generally try to program in "const-correct" form I never make
use of 'const' in "C". - Unless the compiler complains about it,
but I don't recall it (ever?) did.

In my test application I actually never assign string literals
or strings to any other string object (modulo the buffer that I
filled with a 'fgets'). I operate solely with pointers to 'argv'
elements and to the 'char buf[]' buffer data.

Do you see any issue with that?

Janis

[toc] | [prev] | [next] | [standalone]


#390244

FromMichael S <already5chosen@yahoo.com>
Date2025-02-09 19:57 +0200
Message-ID<20250209195711.00001bde@yahoo.com>
In reply to#390235
On Sun, 9 Feb 2025 18:18:04 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:

> On 09.02.2025 11:39, Michael S wrote:
> > On Sun, 9 Feb 2025 10:54:36 +0100
> > Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
> > [...]
> > 
> > There is another problem in your code - it assigns string literal to
> > non-const char*. It is legal, as far as 'C' Standard is concerned,
> > but makes very little practical sense, because any attempt to
> > assign to string literal through resulting pointer is UB. And not
> > just a theoretical UB, but a real-world UB.  
> 
> This comment specifically draw my attention and made me nervous.
> 
> You know, I'm rarely programming in plain "C", and while in C++
> I generally try to program in "const-correct" form 

Which, I suppose, is not easy.

> I never make
> use of 'const' in "C". - Unless the compiler complains about it,
> but I don't recall it (ever?) did.
> 
> In my test application I actually never assign string literals
> or strings to any other string object (modulo the buffer that I
> filled with a 'fgets'). I operate solely with pointers to 'argv'
> elements and to the 'char buf[]' buffer data.
> 
> Do you see any issue with that?
> 
> Janis
> 

I see no issues.

Generally, due to absence of user-defined polymorphism, C does not have
the type of ugly surprises with constness that make life of C++
programmers miserable. Still, behavior of string literals can be
surprising.
I would guess that if it was feasible to make a breaking changes, C89
would define type of string literals as 'const char*' rather than
'char*'. But breaking changes were not feasible.

[toc] | [prev] | [next] | [standalone]


#390245

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-09 19:10 +0100
Message-ID<voar35$oqbe$1@dont-email.me>
In reply to#390244
On 09.02.2025 18:57, Michael S wrote:
> On Sun, 9 Feb 2025 18:18:04 +0100
> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
> 
>> On 09.02.2025 11:39, Michael S wrote:
>>> On Sun, 9 Feb 2025 10:54:36 +0100
>>> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
>>> [...]
>>>
>>> There is another problem in your code - it assigns string literal to
>>> non-const char*. It is legal, as far as 'C' Standard is concerned,
>>> but makes very little practical sense, because any attempt to
>>> assign to string literal through resulting pointer is UB. And not
>>> just a theoretical UB, but a real-world UB.  
>>
>> This comment specifically draw my attention and made me nervous.
>>
>> You know, I'm rarely programming in plain "C", and while in C++
>> I generally try to program in "const-correct" form 
> 
> Which, I suppose, is not easy.

Well, if you start with it there seems to be no end. But once you
understand and got used to it it's like code patterns you apply
without thinking.

> 
>> I never make
>> use of 'const' in "C". - Unless the compiler complains about it,
>> but I don't recall it (ever?) did.
>>
>> In my test application I actually never assign string literals
>> or strings to any other string object (modulo the buffer that I
>> filled with a 'fgets'). I operate solely with pointers to 'argv'
>> elements and to the 'char buf[]' buffer data.
>>
>> Do you see any issue with that?
>>
>> Janis
>>
> 
> I see no issues.

Good to hear.

> 
> Generally, due to absence of user-defined polymorphism, C does not have
> the type of ugly surprises with constness that make life of C++
> programmers miserable. Still, behavior of string literals can be
> surprising.

Actually I think there's a lot that can surprise the unwary in "C". :-)

As "simple" as it is, I wouldn't classify it as an "easy" language
(i.e. it's not one that prevents you from making mistakes).

> I would guess that if it was feasible to make a breaking changes, C89
> would define type of string literals as 'const char*' rather than
> 'char*'. But breaking changes were not feasible.

Janis

[toc] | [prev] | [next] | [standalone]


#390255

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-02-09 16:46 -0800
Message-ID<8734gmr5ig.fsf@nosuchdomain.example.com>
In reply to#390244
Michael S <already5chosen@yahoo.com> writes:
> On Sun, 9 Feb 2025 18:18:04 +0100
> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
>> On 09.02.2025 11:39, Michael S wrote:
>> > On Sun, 9 Feb 2025 10:54:36 +0100
>> > Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
>> > [...]
>> > 
>> > There is another problem in your code - it assigns string literal to
>> > non-const char*. It is legal, as far as 'C' Standard is concerned,
>> > but makes very little practical sense, because any attempt to
>> > assign to string literal through resulting pointer is UB. And not
>> > just a theoretical UB, but a real-world UB.  
>> 
>> This comment specifically draw my attention and made me nervous.
>> 
>> You know, I'm rarely programming in plain "C", and while in C++
>> I generally try to program in "const-correct" form 
>
> Which, I suppose, is not easy.
>
>> I never make
>> use of 'const' in "C". - Unless the compiler complains about it,
>> but I don't recall it (ever?) did.
>> 
>> In my test application I actually never assign string literals
>> or strings to any other string object (modulo the buffer that I
>> filled with a 'fgets'). I operate solely with pointers to 'argv'
>> elements and to the 'char buf[]' buffer data.

There's no such thing as a "string object" in C.  See below.

>> Do you see any issue with that?
[...]
> I see no issues.
>
> Generally, due to absence of user-defined polymorphism, C does not have
> the type of ugly surprises with constness that make life of C++
> programmers miserable. Still, behavior of string literals can be
> surprising.
> I would guess that if it was feasible to make a breaking changes, C89
> would define type of string literals as 'const char*' rather than
> 'char*'. But breaking changes were not feasible.

The type of string literals would be const char[N], not const char*.
(C++ did exactly that.)

In C, a *string* is by definition "a contiguous sequence of characters
terminated by and including the first null character".  A *pointer to a
string* is "a pointer to its initial (lowest addressed) character".  A
string is not a data type; it's a data layout.  An array of char may or
may not have a string *as its contents* (or part of its contents).

A string literal "foo" represents an anonymous array object, in this
case of type char[4].  C++ made string literals const, but C did not.
In C, any attempt to modify the contents of the array object
corresponding to a string literal has undefined behavior.

In C, you can legally write:
    char *ptr = "hello";
but then something like `ptr[0] = 'H';` is legal but has undefined
behavior, and likely will not trigger a warning.  The recommended
practice is that any pointer to a string should be defined with "const":
    const char *ptr = "hello";
so that if you later try `ptr[0] = 'H';` it will be rejected.

Sections 6 and 8 of the comp.lang.c FAQ, <https://www.c-faq.com/>,
cover "Arrays and Pointers" and "Characters and Strings",
respectively.

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

[toc] | [prev] | [next] | [standalone]


#390265

FromJanis Papanagnou <janis_papanagnou+ng@hotmail.com>
Date2025-02-10 02:56 +0100
Message-ID<vobmce$tia0$1@dont-email.me>
In reply to#390255
On 10.02.2025 01:46, Keith Thompson wrote:
> Michael S <already5chosen@yahoo.com> writes:
>> On Sun, 9 Feb 2025 18:18:04 +0100
>> Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
> 
> There's no such thing as a "string object" in C.  [...]

Since I didn't know what Michael was suspecting as a potential
problem I wanted to cover two aspects; assignation  s = "literal"
and  s = strcpy() . (Nothing more was intended to express by my
reply.)

> [ "C" and C++ considerations of strings character arrays, pointers ]

(In C++ I'm not using "C" strings but string objects, plus literal
strings of course.)

Janis

[toc] | [prev] | [next] | [standalone]


#390230

Fromantispam@fricas.org (Waldek Hebisch)
Date2025-02-09 14:29 +0000
Message-ID<voae3a$2rke4$1@paganini.bofh.team>
In reply to#390226
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
> 
> And in "C" (C99) I tried it *without* the _inner block_
> 
> main ()
> {
>   int n = 5;
>   char * arr[n];
>   ...
> }
> 
> and it seemed to work that way. (In those other languages that wasn't
> possible.)

Hmm, IIRC both (Extended) Pascal and PL/I allow VLA within function
in places where they allow variable declarations, so really no
special _inner block_ requirement (just must be local to a function).

>> 
>>> Q1: Is this a correct (portable) form?
>> 
>> VLA objects have to be declared locally. However, keep in mind that
>> support for local declarations of VLA _objects_ is now optional (i.e.
>> not portable). Support for variably-modified _types_ themselves (VLA
>> types) is mandatory. But you are not guaranteed to be able to declare an
>> actual VLA variable.
> 
> I fear I don't understand what you're saying here. - By "now" do you
> mean newer versions of the C standards? That you can rely only, say,
> rely on it with C99 but maybe not before and not in later C standards
> conforming compilers?
> 
> For my purpose it would be okay to know whether with the C99 version
> (that I used) it's okay, or whether that's some GNU specific extension
> or some such.

This used to be GCC extention, AFAIK present in all versions of
GCC.  It was standarized in C99 and is now available in reasonable
C compilers like curent tcc (Tiny C).  But AFAIK it is not present
in Microsoft C.  And probably not present in historic C compilers
like compilers for old proprietary Unices or historic tcc (Tendra
C compiler).  As already mentioned compiler can claim C11 or C23
compliance but do not implement VLA (VMT are optional in C11
but mandatoryu in C23, VLA are optional both in C11 and C23).

-- 
                              Waldek Hebisch

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web