2

I came across this C code that I can't explain to myself:

 check_eeprom_data();
 {

     unsigned char serial_num[5];
     printStr("\nSerNUM:");
     eeprom_read(confEE_SERIAL_NUM, serial_num, 5);
     printBuffAsHex(serial_num, 5);

 }

Why are these curly brackets needed to enclose this part of the code? What makes it different if there were no brackets?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Radoslaw Krasimirow
  • 1,833
  • 2
  • 18
  • 28

8 Answers8

5

The curly brackets are there to allow easy parallel code structure. That is, suppose you wanted to do the same operation again. Without the curly brackets, you would not be able to cut and paste that code block, perhaps with modifications. It is because you can only declare serial_num once at the top of any scope. So it would come out like this:

unsigned char serial_num[5];
printStr("\nSerNUM:");
eeprom_read(confEE_SERIAL_NUM, serial_num, 5);
printBuffAsHex(serial_num, 5);

printStr("\nSerNUM:");
eeprom_read(confEE_SERIAL_NUM, serial_num, 5);
printBuffAsHex(serial_num, 5);

Notice how I can't declare serial_num again? So I can't even keep the block the same I have to delete the line. If I want to introduce a similar block before I would need to move the declaration up. If I wanted to change the length of serial_num I would be stuck because you can only declare serial_num once in any scope.

With curly braces I have a parallel visual structure (ideal for cut and paste with or without modifications) and I also have the flexibility to declare serial_num with different length in each scope.

{
  unsigned char serial_num[5];
  printStr("\nSerNUM:");
  eeprom_read(confEE_SERIAL_NUM, serial_num, 5);
  printBuffAsHex(serial_num, 5);
}

{
  unsigned char serial_num[8];
  printStr("\nSerNUM:");
  eeprom_read(confEE_SERIAL_NUM, serial_num, 8);
  printBuffAsHex(serial_num, 8);
}

Notice how the separate scopes allow one to handle each block independently without interference between them? So I can reorder the blocks even though they use the same symbol name serial_num and not worry about changing the declaration of serial_num. Indeed I can declare serial_num locally as appropriate for each block regardless of if the symbol name matches other blocks or not.

This common pattern is used to increase isolation among distinct local blocks of code that should not be interfering with each other with declarations leaking through from one block to the next. It protects you from symbol name collision and prevents accidental reuse of symbols when you want each block to retain a local flavor despite being similar to other blocks around it.

Rudi Cilibrasi
  • 885
  • 4
  • 12
4

Prior to C99, variables always needed to be defined at the start of a block (before any statements). So if you wanted to define a variable close to where it is being used (and if it only has a short lifetime) then it made sense to introduce a block (i.e. enclose a section of code in braces), as per the example in your question.

Note that many C compilers (particularly embedded compilers, and the notorious Microsoft Visual C compiler) were very slow to support C99, so it's not uncommon to see this style of C89 coding, even today.

Paul R
  • 208,748
  • 37
  • 389
  • 560
3

Local variables declared inside the curly braces live only there (and are visible only there). So when the code leaves the curly braces block serial_num will get destroyed

Andrey Chernukha
  • 21,488
  • 17
  • 97
  • 161
2

That code block is probably there in order to limit the existence of serial_num. When you put braces around some code, you're creating a new scoping block.

Baltasarq
  • 12,014
  • 3
  • 38
  • 57
2

Because in C89 (and K&R C), declarations must be located at the beginning of a block. Note the declaration of unsigned char serial_num[5]; after the opening {. It is good practice to make the scope of variables as small as possible and declare them in the innermost block they are used in.

In C99, declarations can be mixed with code, like in C++.

Jens
  • 69,818
  • 15
  • 125
  • 179
2

They introduce a new scope to limit the lifetime of serial_num (and any other declration made inside). This way, code after the closing brace is not polluted by these variables.

Quentin
  • 62,093
  • 7
  • 131
  • 191
2

In C99 and C11, new local variables can be introduces anywhere in a block of statements, so the braces in your snippet wouldn't be necessary.

However, in C89, the declaration of a new local (block-scope) variable can only occur at the beginning of a block. Therefore, the snippet written as in your example can be compiled with a C89 compiler.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
2

This is used to limit the scope of the variable(s).

In your case,

check_eeprom_data();
 {

  unsigned char serial_num[5];
  printStr("\nSerNUM:");
  eeprom_read(confEE_SERIAL_NUM, serial_num, 5);
  printBuffAsHex(serial_num, 5);
 }

you cannot use serial_num outside that scope.

Also, prior to C99, a variable declaration was mandated at the start of a block. So, to define and use variable(s) within a particular scope, this style / method/ technique is used.

Let's compare this with a simple program, to understand better.

#include <stdio.h>

int main(void) {

    {                           //scope starts
        int p = 5;
            printf("%d", p);    //p is known here
    }                           //scope ends

    printf("%d", p);  // wait, what is p????

    return 0;
}

For the compilation result, see a LIVE EXAMPLE

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261