13

Is it possible to do multiple operations in increment part of for loop in C/C++? Something like this:

int a = 0, b = 0, c = 5;
for(; a < c; increase a by 1 and increase b by 2)
Luka Tiger
  • 298
  • 2
  • 4
  • 10

3 Answers3

25

Use the comma operator:

for (; a < c; ++a, b += 2)
David G
  • 94,763
  • 41
  • 167
  • 253
11

Yes it is possible. You can also declare multiple variables inside the loop and don't need to do it before.

for (int a = 0, b = 0, c = 5; a < c; ++a, b += 2)
AliciaBytes
  • 7,300
  • 6
  • 36
  • 47
  • 2
    What about declaring multiple variables of different types? eg `for(int a=0, char b='A';;)` doesn't work, as it would be expecting `char` to be a variable name. `for(int a=0; char b='A';;)` wouldn't work either, as that places the char declaration in the condition section of the for loop. – Zoey Hewll May 21 '16 at 08:03
  • 3
    @ZoeyHewll multiple declarations in a for loop only works if they are all of the same type. If you need multiple types you'll have to declare them before the loop. Note that you can always use extra `{}` to create a new scope if you need some variables that should only be visible in a limited scope/destroyed automatically afterwards: [Extra brace brackets in C++ code](http://stackoverflow.com/q/3568503/1942027) – AliciaBytes May 21 '16 at 08:23
  • I seem to remember learning about some kind of compound statement enclosed in `()` which can be used in for loops, but perhaps it was in another c-like language. – Zoey Hewll May 22 '16 at 02:15
2

@Zoey Hewll's comment:

What about declaring multiple variables of different types?

@AliciaBytes's comment:

multiple declarations in a for loop only works if they are all of the same type.

This might be close to heresy, but you could use a struct to contain multiple variables of different types like this:

#define BENCHMARK(elasped)                                                     \
    for (                                                                      \
        struct { uint8_t done; uint32_t start; } __metadata =                  \
            { 0, systick_get() };                                              \
        !__metadata.done;                                                      \
        ((elasped) = elasped_time(__metadata.start)), __metadata.done = 1      \
    )

EDIT: Here's a more complete example

#include <stdint.h>
#include <stdio.h>

volatile uint32_t g_systick = 0; //< Incremented by the system clock somewhere else in the code

uint32_t systick_get(void)
{
    return g_systick;
}

uint32_t elasped_time(uint32_t const start)
{
    uint32_t const now = systick_get();
    return now - start;
}

#define BENCHMARK(elasped)                                                     \
    for (                                                                      \
        struct {                                                               \
            uint8_t done;                                                      \
            uint32_t start;                                                    \
        } __metadata = {0, systick_get()};                                     \
        !__metadata.done;                                                      \
        ((elasped) = elasped_time(__metadata.start)), __metadata.done = 1)

int main(void)
{
    uint32_t time = 0;
    BENCHMARK(time)
    {
        int i = 0; //< Something you want to benchmark
    }
    printf("Time = %d\n", time);
    return 0;
}

Here's how the BENCHMARK() macro looks like when expended (using gcc -E)

int main(void) {
    uint32_t time = 0;
    for (
        struct {
            uint8_t done;
            uint32_t start;
        } __metadata = {0, systick_get()};
        !__metadata.done;
        ((time) = elasped_time(__metadata.start)), __metadata.done = 1)
    {
        int i = 0; //< Something you want to benchmark
    }
    printf("Time = %d\n", time);
    return 0;
}

May Dennis Ritchie forgive us.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
gberth
  • 467
  • 5
  • 13
  • 1
    I love this! I always wondered how to get around the one data type constraint, and you just demonstrated it via a `struct`. Can you also post a full, runnable example which includes proper headers and calls this `BENCHMARK()` macro? – Gabriel Staples Jun 29 '22 at 19:01
  • 1
    Glad you like it. Of course. Let me just finish my meeting. – gberth Jun 29 '22 at 19:10
  • Here you go ! Let me know if there's something missing. :^) – gberth Jun 29 '22 at 19:20
  • I haven't tried running it yet, but where are the `systick_get()` and `elapsed_time()` functions defined? Is this on a microcontroller? With an RTOS? I think I'm going to add something like this to my Linux [timinglib](https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/blob/master/c/timinglib.h). – Gabriel Staples Jun 29 '22 at 19:35
  • 1
    It depends on the MCU. On ARM there's a systick timer built it. On PIC32 you need to configure a timer set at 1000Hz yourself if I'm not mistaken. – gberth Jun 29 '22 at 19:46
  • 1
    `there's a systick timer built it` built-in* – gberth Jun 30 '22 at 14:58