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


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

for-loop mutates to an endless-loop

Started by"Walter H." <Walter.H-Nntp@mathemainzel.info>
First post2020-01-03 13:27 +0100
Last post2020-01-04 22:17 +0000
Articles 8 on this page of 68 — 17 participants

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


Contents

  for-loop mutates to an endless-loop "Walter H." <Walter.H-Nntp@mathemainzel.info> - 2020-01-03 13:27 +0100
    Re: for-loop mutates to an endless-loop David Brown <david.brown@hesbynett.no> - 2020-01-03 14:01 +0100
    Re: for-loop mutates to an endless-loop Dan Purgert <dan@djph.net> - 2020-01-03 13:18 +0000
      Re: for-loop mutates to an endless-loop James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-03 08:28 -0500
        Re: for-loop mutates to an endless-loop Dan Purgert <dan@djph.net> - 2020-01-03 13:33 +0000
          Re: for-loop mutates to an endless-loop James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-03 21:10 -0500
      Re: for-loop mutates to an endless-loop David Brown <david.brown@hesbynett.no> - 2020-01-03 15:34 +0100
    Re: for-loop mutates to an endless-loop James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-03 08:26 -0500
      Re: for-loop mutates to an endless-loop "Walter H." <Walter.H-Nntp@mathemainzel.info> - 2020-01-04 16:15 +0100
        Re: for-loop mutates to an endless-loop David Brown <david.brown@hesbynett.no> - 2020-01-04 17:17 +0100
        Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-04 16:20 +0000
          Re: for-loop mutates to an endless-loop "Walter H." <Walter.H-Nntp@mathemainzel.info> - 2020-01-04 18:43 +0100
            Re: for-loop mutates to an endless-loop David Brown <david.brown@hesbynett.no> - 2020-01-04 19:28 +0100
              Re: for-loop mutates to an endless-loop Bart <bc@freeuk.com> - 2020-01-04 18:59 +0000
                Re: for-loop mutates to an endless-loop David Brown <david.brown@hesbynett.no> - 2020-01-05 14:24 +0100
              Re: for-loop mutates to an endless-loop Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-01-04 13:47 -0800
                Re: for-loop mutates to an endless-loop David Brown <david.brown@hesbynett.no> - 2020-01-05 14:26 +0100
                Re: for-loop mutates to an endless-loop "Walter H." <Walter.H-Nntp@mathemainzel.info> - 2020-01-06 20:31 +0100
            Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-04 22:25 +0000
        Re: for-loop mutates to an endless-loop Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2020-01-04 14:08 -0800
        Re: for-loop mutates to an endless-loop James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-04 21:32 -0500
          Re: for-loop mutates to an endless-loop scott@slp53.sl.home (Scott Lurndal) - 2020-01-05 21:48 +0000
        Re: for-loop mutates to an endless-loop James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-01-04 21:43 -0500
    Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-03 14:47 +0100
      Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-03 14:39 +0000
        Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-03 15:42 +0100
          Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-03 15:07 +0000
            Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-03 16:18 +0100
              Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-03 16:47 +0100
                Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-03 20:41 +0000
                  Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 01:05 +0100
              Re: for-loop mutates to an endless-loop gazelle@shell.xmission.com (Kenny McCormack) - 2020-01-03 18:30 +0000
          Re: for-loop mutates to an endless-loop Robert Wessel <robertwessel2@yahoo.com> - 2020-01-04 00:23 -0600
            Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 08:10 +0100
              Re: for-loop mutates to an endless-loop scott@slp53.sl.home (Scott Lurndal) - 2020-01-04 16:41 +0000
                Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 17:44 +0100
            Re: for-loop mutates to an endless-loop Bart <bc@freeuk.com> - 2020-01-04 11:15 +0000
              Re: for-loop mutates to an endless-loop Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-04 12:33 +0000
                Re: for-loop mutates to an endless-loop "Walter H." <Walter.H-Nntp@mathemainzel.info> - 2020-01-04 15:59 +0100
                Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 16:01 +0100
                  Re: for-loop mutates to an endless-loop Jorgen Grahn <grahn+nntp@snipabacken.se> - 2020-01-04 16:04 +0000
                    Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 17:06 +0100
                  Re: for-loop mutates to an endless-loop scott@slp53.sl.home (Scott Lurndal) - 2020-01-04 16:42 +0000
                    Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 17:44 +0100
              Re: for-loop mutates to an endless-loop Robert Wessel <robertwessel2@yahoo.com> - 2020-01-04 17:55 -0600
                Re: for-loop mutates to an endless-loop "Walter H." <Walter.H-Nntp@mathemainzel.info> - 2020-01-06 20:43 +0100
                  Re: for-loop mutates to an endless-loop scott@slp53.sl.home (Scott Lurndal) - 2020-01-06 19:50 +0000
                    Re: for-loop mutates to an endless-loop Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2020-01-06 15:37 -0500
                      Re: for-loop mutates to an endless-loop scott@slp53.sl.home (Scott Lurndal) - 2020-01-06 21:59 +0000
                    Re: for-loop mutates to an endless-loop Robert Wessel <robertwessel2@yahoo.com> - 2020-01-06 17:33 -0600
        Re: for-loop mutates to an endless-loop gazelle@shell.xmission.com (Kenny McCormack) - 2020-01-03 18:31 +0000
          Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 01:06 +0100
            Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-04 01:38 +0000
              Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 08:10 +0100
                Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-04 16:39 +0000
                  Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 17:41 +0100
                    Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-04 17:49 +0100
                      Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-04 22:49 +0000
                        Re: for-loop mutates to an endless-loop Bonita Montero <Bonita.Montero@gmail.com> - 2020-01-05 03:44 +0100
              Re: for-loop mutates to an endless-loop David Brown <david.brown@hesbynett.no> - 2020-01-04 13:09 +0100
    Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-03 14:28 +0000
      Re: for-loop mutates to an endless-loop jak <nospam@please.ty> - 2020-01-05 00:40 +0100
      Re: for-loop mutates to an endless-loop "Walter H." <Walter.H-Nntp@mathemainzel.info> - 2020-01-06 20:50 +0100
        Re: for-loop mutates to an endless-loop Manfred <noname@add.invalid> - 2020-01-06 21:28 +0100
      Re: for-loop mutates to an endless-loop Manfred <noname@add.invalid> - 2020-01-06 21:02 +0100
      Re: for-loop mutates to an endless-loop Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-01-11 10:01 -0800
    Re: for-loop mutates to an endless-loop Richard Damon <Richard@Damon-Family.org> - 2020-01-04 16:21 -0500
      Re: for-loop mutates to an endless-loop Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-01-04 22:17 +0000

Page 4 of 4 — ← Prev page 1 2 3 [4]


#148709

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2020-01-03 14:28 +0000
Message-ID<87ftgwpqbi.fsf@bsb.me.uk>
In reply to#148702
"Walter H." <Walter.H-Nntp@mathemainzel.info> writes:
<cut>
> then I tried the same in C with several compilers
> 32-bit, 64-bit Intel, GNU under Linux or Visual C++ under Windows
> even QuickC or Turbo C every one built this programme with an endless-loop;
>
> [code]
> #include <stdio.h>
> int main( int argc, char* argv[ ] )
> {
>     short int nIter;

This may or may not by a 16-bit integer.  It probably will be, but
modern C has the type int16_t that you can use to be sure.  #include
<stdint.h> to get these new known-width types.

>     long lSum = 0;
>     for ( nIter = -32768; nIter <= 32767; nIter++ )

When you need numbers like this it better to #include <limits.h> and use
SHRT_MIN and SHRT_MAX.  If you included stdint.h to use int16_t then
INT16_MIN and INT16_MAX are available.

Also, in modern C you can declare the loop variable in the for
statement:

  for (short nIter = -32768; nIter <= 32767; nIter++) ...

>         lSum += nIter;
>     printf( "sum: %ld\n", lSum );
>     return 0;
> }
> [/code]

Adding a bit to the answer you already have...

If nInter is indeed a 16-bit integer type, and int is wider (the most
likely situation here) then the behaviour of the code above is
implementation-defined.

Once nIter gets to 32767, the increment in the for loop causes a problem
when the result (which will be of type int) is converted back to short.
The result is either an implementation-defined value or an
implementation-defined signal will be raised.

Anyway, unless a signal is raised, the result is bound to be <= 32767
so, as has been pointed out, the test is never false.

> here the same in old FORTRAN which also worked as expected;
>
> [code]
>       PROGRAM SumDemo
>       INTEGER*2 nIter
>       INTEGER*4 lSum
>       lSum = 0
>       DO nIter = -32768,32767,1
>       lSum = lSum + nIter
>       END DO
>       WRITE ( *, * ) 'sum: ', lSum
>       END
> [/code]

Curiously, the GNU Fortran compiler gets this wrong (at least as far as
my understanding of F77 goes) and generates an endless loop.

<cut>
> what would be the correct way of a for-loop
> with the complete range of an integral type?

One solution is to use a wider type:

  for (int_fast32_t i = INT16_MIN; i <= INT16_MAX; i++) ...

but that is not always possible.  The general solution is to test at the
end, after the increment:

  short i = SHRT_MIN;
  do sum += i; while (i++ < SHRT_MAX);

but this is not portable to implementations where (a) short is as wide
as int (in which case the increment is undefined behaviour), or (b)
implementations that raise a signal when converting an out-of-range
value to short.

A portable solution must increment only when i < SHRT_MAX:

  do sum += i; while (i < SHRT_MAX && i++ | 1);

Of course you can just special-case the last value:

  for (i = SHRT_MIN; i < SHRT_MAX; i++)
      sum += i;
  sum += i;

<cut>
-- 
Ben.

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


#148781

Fromjak <nospam@please.ty>
Date2020-01-05 00:40 +0100
Message-ID<qur7pn$ij6$1@gioia.aioe.org>
In reply to#148709
Il 03/01/2020 15:28, Ben Bacarisse ha scritto:
> "Walter H." <Walter.H-Nntp@mathemainzel.info> writes:
> <cut>
>> then I tried the same in C with several compilers
>> 32-bit, 64-bit Intel, GNU under Linux or Visual C++ under Windows
>> even QuickC or Turbo C every one built this programme with an endless-loop;
>>
>> [code]
>> #include <stdio.h>
>> int main( int argc, char* argv[ ] )
>> {
>>      short int nIter;
> 
> This may or may not by a 16-bit integer.  It probably will be, but
> modern C has the type int16_t that you can use to be sure.  #include
> <stdint.h> to get these new known-width types.
> 
>>      long lSum = 0;
>>      for ( nIter = -32768; nIter <= 32767; nIter++ )
> 
> When you need numbers like this it better to #include <limits.h> and use
> SHRT_MIN and SHRT_MAX.  If you included stdint.h to use int16_t then
> INT16_MIN and INT16_MAX are available.
> 
> Also, in modern C you can declare the loop variable in the for
> statement:
> 
>    for (short nIter = -32768; nIter <= 32767; nIter++) ...
> 
>>          lSum += nIter;
>>      printf( "sum: %ld\n", lSum );
>>      return 0;
>> }
>> [/code]
> 
> Adding a bit to the answer you already have...
> 
> If nInter is indeed a 16-bit integer type, and int is wider (the most
> likely situation here) then the behaviour of the code above is
> implementation-defined.
> 
> Once nIter gets to 32767, the increment in the for loop causes a problem
> when the result (which will be of type int) is converted back to short.
> The result is either an implementation-defined value or an
> implementation-defined signal will be raised.
> 
> Anyway, unless a signal is raised, the result is bound to be <= 32767
> so, as has been pointed out, the test is never false.
> 
>> here the same in old FORTRAN which also worked as expected;
>>
>> [code]
>>        PROGRAM SumDemo
>>        INTEGER*2 nIter
>>        INTEGER*4 lSum
>>        lSum = 0
>>        DO nIter = -32768,32767,1
>>        lSum = lSum + nIter
>>        END DO
>>        WRITE ( *, * ) 'sum: ', lSum
>>        END
>> [/code]
> 
> Curiously, the GNU Fortran compiler gets this wrong (at least as far as
> my understanding of F77 goes) and generates an endless loop.
> 
> <cut>
>> what would be the correct way of a for-loop
>> with the complete range of an integral type?
> 
> One solution is to use a wider type:
> 
>    for (int_fast32_t i = INT16_MIN; i <= INT16_MAX; i++) ...
> 
> but that is not always possible.  The general solution is to test at the
> end, after the increment:
> 
>    short i = SHRT_MIN;
>    do sum += i; while (i++ < SHRT_MAX);
> 
> but this is not portable to implementations where (a) short is as wide
> as int (in which case the increment is undefined behaviour), or (b)
> implementations that raise a signal when converting an out-of-range
> value to short.
> 
> A portable solution must increment only when i < SHRT_MAX:
> 
>    do sum += i; while (i < SHRT_MAX && i++ | 1);
> 
> Of course you can just special-case the last value:
> 
>    for (i = SHRT_MIN; i < SHRT_MAX; i++)
>        sum += i;
>    sum += i;
> 
> <cut>
> 

...or just don't increment last time:

         for (short int nIter = -32768;; nIter++)
         {
                 lSum += nIter;
                 if(!(nIter < 32767))
                         break;
         }

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


#148806

From"Walter H." <Walter.H-Nntp@mathemainzel.info>
Date2020-01-06 20:50 +0100
Message-ID<h7hhc1Ft33kU1@mid.individual.net>
In reply to#148709
On 03.01.2020 15:28, Ben Bacarisse wrote:
> "Walter H."<Walter.H-Nntp@mathemainzel.info>  writes:
>
>> here the same in old FORTRAN which also worked as expected;
>>
>> [code]
>>        PROGRAM SumDemo
>>        INTEGER*2 nIter
>>        INTEGER*4 lSum
>>        lSum = 0
>>        DO nIter = -32768,32767,1
>>        lSum = lSum + nIter
>>        END DO
>>        WRITE ( *, * ) 'sum: ', lSum
>>        END
>> [/code]
>
> Curiously, the GNU Fortran compiler gets this wrong (at least as far as
> my understanding of F77 goes) and generates an endless loop.

mine worked as expected, the same with Turbo Pascal, probably any other 
Pascal, too;

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


#148809

FromManfred <noname@add.invalid>
Date2020-01-06 21:28 +0100
Message-ID<qv058q$mav$1@gioia.aioe.org>
In reply to#148806
On 1/6/2020 8:50 PM, Walter H. wrote:
> On 03.01.2020 15:28, Ben Bacarisse wrote:
>> "Walter H."<Walter.H-Nntp@mathemainzel.info>  writes:
>>
>>> here the same in old FORTRAN which also worked as expected;
>>>
>>> [code]
>>>        PROGRAM SumDemo
>>>        INTEGER*2 nIter
>>>        INTEGER*4 lSum
>>>        lSum = 0
>>>        DO nIter = -32768,32767,1
>>>        lSum = lSum + nIter
>>>        END DO
>>>        WRITE ( *, * ) 'sum: ', lSum
>>>        END
>>> [/code]
>>
>> Curiously, the GNU Fortran compiler gets this wrong (at least as far as
>> my understanding of F77 goes) and generates an endless loop.
> 
> mine worked as expected, the same with Turbo Pascal, probably any other 
> Pascal, too;

Actually with f77 it doesn't play nice either (gfortran compiles f95 and 
later resulting in an endless loop indeed):

$ f77 --version
GNU Fortran (GCC) 3.4.6 20060404 (Red Hat 3.4.6-46.fc28)
Copyright (C) 2006 Free Software Foundation, Inc.

$ f77 full_loop.f
full_loop.f: In program `sumdemo':
full_loop.f:5: warning:
           DO nIter = -32768,32767,1
                      ^
Iterative DO loop begin, end, and step-count values known to result in 
no iterations at (^)
full_loop.f:5: warning:
           DO nIter = -32768,32767,1
                             ^
Iterative DO loop end value plus step count known to overflow at (^)

$ ./a.out
  sum:  0

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


#148808

FromManfred <noname@add.invalid>
Date2020-01-06 21:02 +0100
Message-ID<qv03o5$esp$1@gioia.aioe.org>
In reply to#148709
On 1/3/2020 3:28 PM, Ben Bacarisse wrote:
> A portable solution must increment only when i < SHRT_MAX:
> 
>    do sum += i; while (i < SHRT_MAX && i++ | 1);

I find that somehow stinging for the eye.

    do sum += i; while (i < SHRT_MAX && (++i, 1));

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


#148939

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2020-01-11 10:01 -0800
Message-ID<86pnfp27oz.fsf@linuxsc.com>
In reply to#148709
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:

> "Walter H." <Walter.H-Nntp@mathemainzel.info> writes:
> <cut>
>
>> then I tried the same in C with several compilers
>> 32-bit, 64-bit Intel, GNU under Linux or Visual C++ under Windows
>> even QuickC or Turbo C every one built this programme with an endless-loop;
>>
>> [code]
>> #include <stdio.h>
>> int main( int argc, char* argv[ ] )
>> {
>>     short int nIter;
>
> This may or may not by a 16-bit integer.  It probably will be, but
> modern C has the type int16_t that you can use to be sure.  #include
> <stdint.h> to get these new known-width types.
>
>>     long lSum = 0;
>>     for ( nIter = -32768; nIter <= 32767; nIter++ )
>
> When you need numbers like this it better to #include <limits.h> and use
> SHRT_MIN and SHRT_MAX.  If you included stdint.h to use int16_t then
> INT16_MIN and INT16_MAX are available.
>
> Also, in modern C you can declare the loop variable in the for
> statement:
>
>   for (short nIter = -32768; nIter <= 32767; nIter++) ...
>
>>         lSum += nIter;
>>     printf( "sum: %ld\n", lSum );
>>     return 0;
>> }
>> [/code]
>
> Adding a bit to the answer you already have...
>
> If nInter is indeed a 16-bit integer type, and int is wider (the most
> likely situation here) then the behaviour of the code above is
> implementation-defined.
>
> Once nIter gets to 32767, the increment in the for loop causes a problem
> when the result (which will be of type int) is converted back to short.
> The result is either an implementation-defined value or an
> implementation-defined signal will be raised.
>
> Anyway, unless a signal is raised, the result is bound to be <= 32767
> so, as has been pointed out, the test is never false.
>
>> here the same in old FORTRAN which also worked as expected;
>>
>> [code]
>>       PROGRAM SumDemo
>>       INTEGER*2 nIter
>>       INTEGER*4 lSum
>>       lSum = 0
>>       DO nIter = -32768,32767,1
>>       lSum = lSum + nIter
>>       END DO
>>       WRITE ( *, * ) 'sum: ', lSum
>>       END
>> [/code]
>
> Curiously, the GNU Fortran compiler gets this wrong (at least as far as
> my understanding of F77 goes) and generates an endless loop.
>
> <cut>
>
>> what would be the correct way of a for-loop
>> with the complete range of an integral type?
>
> One solution is to use a wider type:
>
>   for (int_fast32_t i = INT16_MIN; i <= INT16_MAX; i++) ...
>
> but that is not always possible.  The general solution is to test at the
> end, after the increment:
>
>   short i = SHRT_MIN;
>   do sum += i; while (i++ < SHRT_MAX);
>
> but this is not portable to implementations where (a) short is as wide
> as int (in which case the increment is undefined behaviour), or (b)
> implementations that raise a signal when converting an out-of-range
> value to short.
>
> A portable solution must increment only when i < SHRT_MAX:
>
>   do sum += i; while (i < SHRT_MAX && i++ | 1);

Another way to achieve the same effect:

    do sum += i; while (i < SHRT_MAX && i++ < SHRT_MAX);

(It seems likely that optimization will omit the redundant
comparison.)

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


#148770

FromRichard Damon <Richard@Damon-Family.org>
Date2020-01-04 16:21 -0500
Message-ID<Hl7QF.26306$gQ2.20665@fx25.iad>
In reply to#148702
I will point that there is a fundamental limitation in the for loop, 
that when running on cycling the value of a variable, there MUST be some 
value that won't be used in the loop, to use for the exit case. Since 
the test clause is run BEFORE each loop, if it is testing the value of 
the loop variable, there needs to be a value that the loop won't run on 
to test for and exit the loop.

I know of two options here, one is to just use a wide variable for the 
loop, so if you want all value of an int to be used, then you need to 
choose a type for the loop counter that is bigger than an int.

A second option is to switch from a for loop to a do while of the form:

var = start value for loop
do {
   // Code for loop
   if(var == max value for loop) break
   var++
} while (1);

IF (and only if) the compiler promises not to optimize on the undefined 
behavior, and the actual undefined behavior of increment is benign, then 
(and only then) you can combine the test and the increment into the 
while clause, to get something like:

var = start value for loop
do {
   // Code for loop
} while(var++ != max value for loop);

Note, by checking the value before the increment we can test for the 
last value, but because the increment will still happen, the undefined 
behavior of the overflow does happen, so it must be benign and not 
optimized against.

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


#148774

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2020-01-04 22:17 +0000
Message-ID<87v9pqn9xy.fsf@bsb.me.uk>
In reply to#148770
Richard Damon <Richard@Damon-Family.org> writes:

> I will point that there is a fundamental limitation in the for loop,
> that when running on cycling the value of a variable, there MUST be
> some value that won't be used in the loop, to use for the exit
> case. Since the test clause is run BEFORE each loop, if it is testing
> the value of the loop variable, there needs to be a value that the
> loop won't run on to test for and exit the loop.
>
> I know of two options here, one is to just use a wide variable for the
> loop, so if you want all value of an int to be used, then you need to
> choose a type for the loop counter that is bigger than an int.
>
> A second option is to switch from a for loop to a do while of the form:
>
> var = start value for loop
> do {
>   // Code for loop
>   if(var == max value for loop) break
>   var++
> } while (1);

There is a "tricksy" partial for-based solution as well.  If the loop
body is made up of expression statements, or you can re-write it as a
function, you can write

  for (T i = min-value-of-T; f(... i ...), i < max-value-of-T; i++);

In the case in question one can write:

  long sum = 0;
  for (short i = SHRT_MIN; sum += i, i < SHRT_MAX; i++);
  printf("%ld\n", sum);

The idea cones form Algol 68 where every expression can be a
value-yielding block.  This gave one a way to do exit in the middle
loops without break by writing part of the loop body in the while
condition.

If you have block expressions (as gcc provides) this is in fact a
general solution, though it probably still rates as yucky for normal
programmers.

> IF (and only if) the compiler promises not to optimize on the
> undefined behavior, and the actual undefined behavior of increment is
> benign, then (and only then) you can combine the test and the
> increment into the while clause, to get something like:
>
> var = start value for loop
> do {
>   // Code for loop
> } while(var++ != max value for loop);
>
> Note, by checking the value before the increment we can test for the
> last value, but because the increment will still happen, the undefined
> behavior of the overflow does happen, so it must be benign and not
> optimized against.

Yup, for signed types no narrower than int.  As I am sure you know,
there will be no UB if var is unsigned, and if var has a type narrower
than int the behaviour is implementation defined.

-- 
Ben.

[toc] | [prev] | [standalone]


Page 4 of 4 — ← Prev page 1 2 3 [4]

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


csiph-web