Is it possible to do multiple operations in increment part of for loop in C/C++?
Asked Answered
H

3

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)
Haag answered 7/10, 2013 at 23:40 Comment(1)
Note for when this is reopened: add an answer about GNU statement expressions.Paymar
Z
25

Use the comma operator:

for (; a < c; ++a, b += 2)
Zygophyte answered 7/10, 2013 at 23:41 Comment(0)
Q
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)
Quartz answered 7/10, 2013 at 23:47 Comment(3)
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.Translucid
@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++ codeQuartz
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.Translucid
V
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.

Valuation answered 29/6, 2022 at 18:55 Comment(6)
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?Stacistacia
Glad you like it. Of course. Let me just finish my meeting.Valuation
Here you go ! Let me know if there's something missing. :^)Valuation
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.Stacistacia
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.Valuation
there's a systick timer built it built-in*Valuation

© 2022 - 2024 — McMap. All rights reserved.