0

Sorry if I am asking a stupid question, but I can't find the answer due to clumsy search terms I guess

If I declare three variables as follows

volatile uint16_t a, b, c;

Will all three variables be declared volatile?

Or should I really not declare multiple variables in a row but instead do:

volatile uint16_t a;
volatile uint16_t b;
volatile uint16_t c;
bas
  • 13,550
  • 20
  • 69
  • 146
  • 3
    `volatile` qualifies a type, not a variable (see e.g. [here](https://en.cppreference.com/w/c/language/volatile) for more documentation). – Nelewout May 18 '21 at 08:57
  • 1
    Yes, in your example the `volatile` is part of the "declaration specifiers" (it's a type-qualfier along with `const` and `restrict`) and applies to each of the "declarators" in the comma-separated list. It's section 6.7 of the standard, although it's quite hard to wade through and make sense of. – Paul Hankin May 18 '21 at 09:12
  • 2
    You should declare one variable per line anyway. – user7860670 May 18 '21 at 09:16
  • Will all variables be `uint16_t` ??? if not, what type are the other variables? – Luis Colorado May 19 '21 at 15:47
  • They will be. The nasty part lies in initializing them. – bas May 19 '21 at 16:18

2 Answers2

3

If I declare three variables as follows

volatile uint16_t a, b, c;

Will all three variables be declared volatile?

Yes, all 3 variables will be volatile.

Or should I really not declare multiple variables in a row but instead do:

That is related to code style and personal preference. Usually declaring variables one per line is preferred, is more readable, easier to read, easier to refactor and results in more readable changes when browsing diff output of files.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • "That is related to code style and personal preference" Not really. Declaring several variables on the same line is plain bad for many reasons. Not just the confusion regarding volatile, const, static etc, but particularly when mixing pointer declarations with ordinary object declarations. If this was a style issue then there would also be valid arguments in favour for it, but there are none. – Lundin May 18 '21 at 12:56
0

We can check the assembly generated by the compiler to see if it optimizes the variables out or not.

When I check this simple program:

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

int main(void)
{
    uint16_t a = 1, b = 1, c = 1;
    printf("%hu", a);
    printf("%hu", b);
    printf("%hu", c);
}

The generated assembly at -O3 (link) is:

.LC0:
        .string "%hu"
main:
        sub     rsp, 8
        mov     esi, 1
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        mov     esi, 1
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        mov     esi, 1
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        xor     eax, eax
        add     rsp, 8
        ret

It's obvious here that the variables have been optimized out and 1 is being used as a parameter instead of the variables.

When I replace the uint16_t a = 1, b = 1, c = 1; with volatile uint16_t a = 1, b = 1, c = 1;, The assembly generated (link) is:

main:
        sub     rsp, 24
        mov     edx, 1
        mov     ecx, 1
        mov     eax, 1
        mov     WORD PTR [rsp+10], ax
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        mov     WORD PTR [rsp+12], dx
        mov     WORD PTR [rsp+14], cx
        movzx   esi, WORD PTR [rsp+10]
        call    printf
        movzx   esi, WORD PTR [rsp+12]
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        movzx   esi, WORD PTR [rsp+14]
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        xor     eax, eax
        add     rsp, 24
        ret

Here, volatile is working like it should for all variables. The variables are created and are not optimized out.

In comparison, if we replace volatile uint16_t a = 1, b = 1, c = 1; with volatile uint16_t a = 1; uint16_t b = 1, c = 1; we see that only a is not optimized out (link):

main:
        sub     rsp, 24
        mov     eax, 1
        mov     edi, OFFSET FLAT:.LC0
        mov     WORD PTR [rsp+14], ax
        movzx   esi, WORD PTR [rsp+14]
        xor     eax, eax
        call    printf
        mov     esi, 1
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        mov     esi, 1
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax
        call    printf
        xor     eax, eax
        add     rsp, 24
        ret
mediocrevegetable1
  • 4,086
  • 1
  • 11
  • 33
  • 1
    I didn't downvote, but answering questions about C using experiments is often flawed since compilers may or may not adhere exactly to the standard, and even if they do you don't know if what you're seeing is in the range of implementation-defined behavior or guaranteed. – Paul Hankin May 18 '21 at 09:19
  • @PaulHankin thinking about it now, I guess you're right, I hadn't thought about that possibility. I just tested based on my assumption of what volatile was meant to do ¯\\_(ツ)_/¯ – mediocrevegetable1 May 18 '21 at 09:22