Variable in for-loop is acting weird

Hi,
I have a piece of code (see below). When i run the code I get output 1. But in the serial monitor, I never see the word "pointa" or "pointb". I have already found what is causing this. If i set the line offset = 1000*i in comment, the problem is solved. Then i get output 2.

I do not understand how this is possible. Does anyone have an explanation for this?
Thank you in advance.

This is the code:

long offset = 0;
long numberMeausurementsRequest_int = 1200;
String input = "";

void setup() { // wait for serial to start
  Serial.begin(115200);
    while (!Serial) {
  }
  randomSeed(analogRead(0));
}

void loop() { 
for (int i = 0; i<numberMeausurementsRequest_int ;i=i+3){
      offset = 1000*i; // <<-----------------------------------------
      if ((i > 500)&&(i<600)){ 
        Serial.println(String(i) + "pointa");
      }
      else if ((i > 700)&&(i<710)){ 
        Serial.println(String(i) + "pointb");
      }
      else{
        Serial.println(i);
      }
    }
    Serial.println("#");  
}

output 1:

0
3
6
9
12
15
18
21
24
27
30
33
36
39
42
45
48
51
54
57
60
63
66
69
72
75
78
81
84
87
90
93
96
99
102
105
108
111
114
117
120
123
126
129
132
135
138
141
144
147
150
153
156
159
162
165
168
171
174
177
180
183
186
189
192
195
198
201
204
207
210
213
216
219
222
225
228
231
234
237
240
243
246
249
252
255
258
261
264
267
270
273
276
279
282
285
288
291
294
297
300
303
306
309
312
315
318
321
324
327
330
333
336
339
342
345
348
351
354
357
360
363
366
369
372
375
378
381
384
387
390
393
396
399
402
405
408
411
414
417
420
423
426
429
432
435
438
441
444
447
450
453
456
459
462
465
468
471
474
477
480
483
486
489
492
495
498
501
504
507
510
513
516
519
522
525
528
531
534
537
540
543
546
549
552
555
558
561
564
567
570
573
576
579
582
585
588
591
594
597
600
603
606
609
612
615
618
621
624
627
630
633
636
639
642
645
648
651
654
657
660
663
666
669
672
675
678
681
684
687
690
693
696
699
702
705
708
711
714
717
720
723
726
729
732
735
738
741
744
747
750
753
756
759
762
765
768
771
774
777
780
783
786
789
792
795
798
801
804
807
810
813
816
819
822
825
828
831
834
837
840
843
846
849
852
855
858
861
864
867
870
873
876
879
882
885
888
891
894
897
900
903
906
909
912
915
918
921
924
927
930
933
936
939
942
945
948
951
954
957
960
963
966
969
972
975
978
981
984
987
990
993
996
999
1002
1005
1008
1011
1014
1017
1020
1023
1026
1029
1032
1035
1038
1041
1044
1047
1050
1053
1056
1059
1062
1065
1068
1071
1074
1077
1080
1083
1086
1089
1092
1095
1098
1101
1104
1107
1110
1113
1116
1119
1122
1125
1128
1131
1134
1137
1140
1143
1146
1149
1152
1155
1158
1161
1164
1167
1170
1173
1176
1179
1182
1185
1188
1191
1194
1197
#

output 2:

0
3
6
9
12
15
18
21
24
27
30
33
36
39
42
45
48
51
54
57
60
63
66
69
72
75
78
81
84
87
90
93
96
99
102
105
108
111
114
117
120
123
126
129
132
135
138
141
144
147
150
153
156
159
162
165
168
171
174
177
180
183
186
189
192
195
198
201
204
207
210
213
216
219
222
225
228
231
234
237
240
243
246
249
252
255
258
261
264
267
270
273
276
279
282
285
288
291
294
297
300
303
306
309
312
315
318
321
324
327
330
333
336
339
342
345
348
351
354
357
360
363
366
369
372
375
378
381
384
387
390
393
396
399
402
405
408
411
414
417
420
423
426
429
432
435
438
441
444
447
450
453
456
459
462
465
468
471
474
477
480
483
486
489
492
495
498
501pointa
504pointa
507pointa
510pointa
513pointa
516pointa
519pointa
522pointa
525pointa
528pointa
531pointa
534pointa
537pointa
540pointa
543pointa
546pointa
549pointa
552pointa
555pointa
558pointa
561pointa
564pointa
567pointa
570pointa
573pointa
576pointa
579pointa
582pointa
585pointa
588pointa
591pointa
594pointa
597pointa
600
603
606
609
612
615
618
621
624
627
630
633
636
639
642
645
648
651
654
657
660
663
666
669
672
675
678
681
684
687
690
693
696
699
702pointb
705pointb
708pointb
711
714
717
720
723
726
729
732
735
738
741
744
747
750
753
756
759
762
765
768
771
774
777
780
783
786
789
792
795
798
801
804
807
810
813
816
819
822
825
828
831
834
837
840
843
846
849
852
855
858
861
864
867
870
873
876
879
882
885
888
891
894
897
900
903
906
909
912
915
918
921
924
927
930
933
936
939
942
945
948
951
954
957
960
963
966
969
972
975
978
981
984
987
990
993
996
999
1002
1005
1008
1011
1014
1017
1020
1023
1026
1029
1032
1035
1038
1041
1044
1047
1050
1053
1056
1059
1062
1065
1068
1071
1074
1077
1080
1083
1086
1089
1092
1095
1098
1101
1104
1107
1110
1113
1116
1119
1122
1125
1128
1131
1134
1137
1140
1143
1146
1149
1152
1155
1158
1161
1164
1167
1170
1173
1176
1179
1182
1185
1188
1191
1194
1197
#

Can you post the entire code please. I'm curious if you have defined your variables in some conflicting way

int times int is prone to overflow

Irrational behaviour of the code is often due to a mistake that is made elsewhere in the code than where you see the symptoms. For example, if you exceed array bounds, unpredictable memory locations can be modified. The effects can be extremely random. That is why we want to see the entire sketch.

with warnings turned on i get the following

C:\Tools\Arduino\hardware\arduino\avr\cores\arduino\main.cpp: In function 'main':
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:12:22: warning: iteration 11 invokes undefined behavior [-Waggressive-loop-optimizations]
         offset = 1000*i; // <<-----------------------------------------
                      ^
C:\stuff\SW\Arduino\_Others\Tst\Tst.ino:11:22: note: within this loop
     for (int i = 0; i<numberMeausurementsRequest_int ;i=i+3){
                      ^

the computation is done as an int and therefore exceeds 32768. not sure why this causes the problem

replacing with

offset = 1000L*i;

seems to fix it.

1 Like

The full code is below. To test the code, enter "START1000" in the serial monitor.

// ------ this program print fake data to the serial monitor ------

long offset = 0;
long pulseTime1 = 0;
long pulseTime2 = 0;
long pulseTime3 = 0;

int chort = 100;
int medium = 300;
int lang = 600;

long numberMeausurementsRequest_int = 1200;

String input = "";

void setup() {
  Serial.begin(115200);
    while (!Serial) {
    ; // wait for serial port to connect.
  }
  randomSeed(analogRead(0));
}


void loop() { 
  char input_serial_str[10];
  int idx = 0;
//--------- detect the word "START" and take the numbers after that word -- (this part is working)-----------
  while (Serial.available() == 0) {} // wait for user input
  input = Serial.readString();
  if (input[0] == 'S' && input[1] == 'T'&& input[2] == 'A'&& input[3] == 'R' && input[4] == 'T'){
    
    String numberMeasurementsRequest = "";
    long numberMeausurementsRequest_int = 0;
    for (int x = 5; x< input.length()-1; x++){
      numberMeasurementsRequest = numberMeasurementsRequest + input[x];
    }
    numberMeausurementsRequest_int = numberMeasurementsRequest.toInt();
    Serial.println(numberMeausurementsRequest_int); 
    
// -----------------------------------------------------------------------------------------------

// -------print to the serial monitor ----(this part is not working)------------------------------
    // eerste soort pulsen -_-__-____
    for (int i = 0; i<numberMeausurementsRequest_int ;i=i+3){
      offset = 1000*i;
      pulseTime1 = offset +3;
      pulseTime2 = pulseTime1 + chort;
      pulseTime3 = pulseTime2 + medium;
      if ((i > 500)&&(i<600)){ 
        Serial.println(String(i) + "pointa");
        Serial.println(String(random(235,255)) + ";" + String(pulseTime1)); // amplitude + ";" + time
        Serial.println(String(random(200,210)) + ";" + String(pulseTime2));
        Serial.println(String(random(235,255)) + ";" + String(pulseTime3));
      }
      else if ((i > 700)&&(i<710)){ 
        Serial.println(String(i) + "pointb");
        Serial.println(String(random(235,255)) + ";" + String(pulseTime1)); // amplitude + ";" + time
        Serial.println(String(random(200,210)) + ";" + String(pulseTime2));
        Serial.println(String(random(235,255)) + ";" + String(pulseTime3));
      }
      else{
        Serial.println(i);
        Serial.println(String(random(174,199)) + ";" + String(pulseTime1));
        Serial.println(String(random(200,210)) + ";" + String(pulseTime2));
        Serial.println(String(random(174,199)) + ";" + String(pulseTime3));
      }
    }
    Serial.println("#");   
    input = "";
  } 
}

@gcjr Thank you. Now it works.

Looks like a compiler error. Is integer overflow supposed to be "undefined behavior"?!?

Also true. At least In this case, the variable definition of int (times int) resulted in a value overflow, so I am glad to see that I helped the issue and it has been resolved.

Perhaps, if it can not be predicted at compile time, e.g. consider

long j = 1000 * i;

vs.

long j = 1000 * 1000;

???

But it WAS predicted at compile time. :slight_smile:

/Users/john/Documents/Arduino/sketch_aug11b/sketch_aug11b.ino:11:19: warning: iteration 33 invokes undefined behavior [-Waggressive-loop-optimizations]
     offset = 1000 * i;
              ~~~~~^~~
void setup()
{
  Serial.begin(115200);
  while (!Serial) {}
  delay(200);

  unsigned long offset;

  for (int i = 0; i < 100; i++)
  {
    offset = 1000 * i;
  }
}

void loop() {}

What is the 'undefined behavior' in 'iteration 33' if not the integer overflow when 1000 is multiplied by 33? :slight_smile:

1 Like

Yeah, in this case the 'for' loop parameters guarantee that 'i' will exceed 32. I wonder what would happen if not? For example, if 'i' were the product of some complex calculation?

It is in C.

a7

Looks like C++, too.
https://en.cppreference.com/w/c/language/operator_arithmetic
I hadn't thought about the various ways of storing signed numbers.

If I change 'i' from 'int' to 'unsigned' the compiler doesn't bother to warn that 'iteration 66 invokes integer overflow' even though it was happy to point out 'iteration 33 invokes undefined behavior'.

That's because overflow in unsigned integers is not undefined beviuour!

It is well defined and often exploited, and probably something one can be forgiven for expecting to be the same w/ signed ints.

And maybe in 99.44 it is OK.

The only fault would be a compiler that failed to issue the warning, or we who fly close to the sun with warnings turnt off or just ignored.

a7

Indeed, isn't this the very thing that allows us to handle micros() and millis() rollovers?