Meaning of lone curly-braced code blocks in C - c

I've come across a bit of code that contains a couple code blocks, delineated with curly braces {}. There is no line before the code blocks marking them as part of if statements, function definitions, or anything else. Just a code block floating in the middle of a function. Is there any meaning to this? gcc seems perfectly happy going through the code; I can only imagine it is some way to allow the original coder to split up blocks of functionality visually...

It creates a scope. Are there automatic variables defined inside the blocks? If so, then the scope of those variables is confined to the block. It's useful for temporary variables that you don't want polluting the rest of the function, and it's also useful when writing C89, where variable definitions must be at the start of a block.
So, instead of:
int main() {
int a = 0;
int b;
int i;
for (i = 1; i < 10; ++i) {
a += i;
}
b = a * a;
// do something with a and b
}
You could have:
int main() {
int a = 0;
{
int i;
for (i = 1; i < 10; ++i) {
a += i;
}
}
{
int b = a * a;
// do something with a and b
}
}
Obviously if you're doing this, you also have to ask yourself if the blocks wouldn't be better off as separate functions.

Standalone curly braces are used for scoping—any variables declared in a block aren't visible outside it.

If the code blocks contain local variable declarations (your description is not clear about what's inside), they may be there to limit the scope of those variables. I.e.
int i = ...;
// i is visible here
{
int j = ...;
// both i and j are visible here
}
// j went out of scope, only i is visible here

It is used to create a scope. A scope if useful to declare variables that can only be used inside this scope. For example, if a variable is declared before the braces, it can be used inside the braces of after them. At the contrary, if a variable is declared inside the braces, it can only be used inside the braces.
Hope this helps.

It usually means it was written to declare a variable part way through a larger function, but the variable only needs a very limited scope, or may even need to hide something. It is entirely legimitate - it simply introduces a block. The big issue is always "what is the correct indentation for that code".
It can also be used by pre-processors that convert some other language into generated C. The converted material is often wrapped in a block (and possibly #line directives too).

Related

How to change the scope of a variable, defined inside a for-loop inside an if conditional, to use it outside?

if(condition)
{
for(int i=10; i>=0 ; i--)
{
//Wanted to change the scope of the variable "i"
}
}
I want to change the scope of variable i;
so that it can be used outside the if statement.
Here is how to make variable i useable outside of if() (without turning it into a global variable, i.e. heeding the recommendations in the comments, which I agree with).
Just define (and preferrably initialise) the variable before (i.e. outside) of if(). This makes whatever scope the if() is in the scope of the variable.
Just move the definition far enough outwards to make it useable where you want it.
Important is to then NOT define it inside the if(){} again, i.e. remove the original/second int, so that whatever you do inside stays visible outside.
With another definition within if, there would be a local variable shadowing the one you want to use.
int i=9; /* initialised, out of habit */
i++; // useable here, now 10, but your intended use might result in other values
if(condition)
{
for(i=10; i>=0 ; i--) /* assign 10, to make sure */
{
// whatever
}
}
i++; // also useable here

Practical use of extra braces in C

I know {} are used to separate entities such as functions, classes and conditional branching, but what other use would they have here?
#import <stdio.h>
int main(void) {
{{{
printf("main\n");
}}}
return 0;
}
EDIT:
I found that it may be useful primarily for information hiding, along with nested functions. From the answers below it would seem they can be used as a marker during debugging and be removed in the release, but that this should not be endorsed.
Enclosing a code in braces { } creates an Scope.
Creating an local scope can have number of reasons like:
Allows you to reuse a variable name in enclosing scope.
Define variables in middle of function.
Creating variables anywhere except at the start of an scope was not allowed in c89, but it is allowed since c99.
Online Example Code Sample:
#include<stdio.h>
int main()
{
int i = 10;
{
int i = 5;
printf("i is [%d]\n",i);
}
printf("i is [%d]\n",i);
return 0;
}
In your example code,
the extra { & } do not serve any purpose, they are just redundant code.
As #Martin suggests in comments, since enclosing code in {{{ & }}} is just similar to { & }, it might be used as an tag/pattern for easy search.
However, Personally, I would prefer adding appropriate comment to the code with an keyword which would show up in search rather than add such redundant code.
That syntax (three curly braces in a row) doesn't mean anything special in standard C. The author of such code might use it to indicate something about the code inside, like that it's just there for debugging.
you can introduce a new scope, which then allows you to introduce new variables.... which can be useful in C89. Not too normal though, but occasionally useful.
{
int x =2 ;
printf("%d", x);
{
int y = 7;
printf("%d", y);
}
}
Extra braces gives you scope as Als mentioned. This can be used in case of Smart Pointers effectively. e.g., consider the following code in C++ (MSVC compiler)
int i = 0;
i++;
//More code follows
...
{
CComBSTR bstr("Hello");
//use this bstr in some code
.....
}
After the end braces, bstr won't be available. Furthermore, since it has gone out of scope, therefore, the destructor will also get called automatically.

Putting variable declarations in a separate function in C

Is it possible to put the variable declarations in an external function? After reading from Wikipedia that:
an inline function is a function upon which the compiler has been requested to perform inline expansion. In other words, the programmer has requested that the compiler insert the complete body of the function in every place that the function is called, rather than generating code to call the function in the one place it is defined.
I hypothesized that the following might work. It did not take long for the compiler to slap my fingers :(
inline void declaration(){
int a;
}
int main(){
declaration();
a=2;
return 0;
}
This may not be how it is done but if you want a basic idea of how you can think about what happens when you inline a function.
Imagine the compiler turning your code into something like this, then you see why it will not work.
int main(){
{
int a;
}
a=2;
return 0;
}
The call to declaration() is replaced by the contents of the function including brackets, thus int a; is declared in an inner scope and is not visible in the main function.
No, this is not possible.
What is possible, is to use a preprocessor directive #define:
#define VARBLOCK int a, b, c; char ca, cb, cc;
int main()
{
VARBLOCK;
a = 2;
}
This would be a bad practice. Also these would still be variables only available in the scope of function where it were placed, without values being shared.
No - as far as I'm aware an inline function must behave semantically equivalent to a non-inline function; it doesn't affect what counts as legal code. It's just an optimization.
In particular, you could have a variable called a in both functions, but they'd be separate variables on the stack.
(Even if you could do this, I'd suggest it would be a very bad idea in terms of readability.)
inline functions are usually just a function containing no more than about 4 lines and you would want the compiler to do the optimization you where talking about since it would be faster to do what the function does, rather than adding extra code.
Inline expansion is used to eliminate the time overhead when a function is called. It is typically used for functions that execute frequently.
So there's nothing special with the inline function, rather than it might be handled differently by the compiler. They don't share their stack with any other function, which would be the only way for main to use a variable that is created in a different scope.
So my tip is; write your functions, and treat them as you usally should. Then when you are done, inline the short ones that you use a lot.
And if you really wanna create a variable in another function, allocate it on the heap in the function and return a pointer that you save and then set to 2 (your case). :) Just remember to free the memory!
You can do this, though:
#include <stdio.h>
int* GetMyIntAddress(void)
{
static int blah = 0;
return &blah;
}
int main(void)
{
printf("%d\n", *GetMyIntAddress());
*GetMyIntAddress() = 123;
printf("%d\n", *GetMyIntAddress());
return 0;
}
blah will be a global variable defined in the scope of the GetMyIntAddress() function.
If you add inline to the definition of GetMyIntAddress(), you are risking to get multiple independent instances of blah if the inline function is used in different modules (e.g. included from a shared header file).

Terminology definition - Scope in C application

Is there a specific term for the following type of C code? In my example, I want to increase the depth of scope for a small chunk of code within a function without having to use needless if/else/for statements so that I can re-declare a variable with the same name multiple times. eg:
void myfunc(void) {
int a = 0, b = 1;
{
int c;
c = 3;
printf("c is: %d", c);
}
a = 2;
{
int c = 5;
printf("c is %d", c);
}
}
What is the term used to describe how I just wrapped some code in curly braces and increased the scope depth so the rest of the function doesn't see the 'c' int?
Thanks!
Scope is defined as the area in which the object is active. There are five scopes in C. They are as follows.
Program Scope
These are the declarations at the top most layers. They are available up to the life of a program. All the functions have this scope. This is otherwise known as global scope.
File Scope
It has scope such that it may be accessed from that point to the end of the file.
void dummy(void) { }
// absence of static automatically gives program scope to `dummy()`
static void dummy(void) { }
// static keyword here gives function `dummy()` a file scope
Function Scope
Only labels have this scope. In this scope, they are active up to end of the function.
void printFun()
{
print:
printf(“i is less than j”);
}
int main()
{
int i=1,j=2;
if(i < j)
goto print;
}
This code will be flagged error by the compiler saying that the label print is not known because labels have only function scope. If you have to jump unconditionally between the functions, you have to use setjmp/longjmp functions.
Block Scope
Declarations that are active up to the end of the block (where a block is defined as statements within { }). All the declarations inside the function have only block scope.
int fun(int a, int b)
{
int c;
{
int d;
}
// a, b, c, d all have block scope
}
As I have said, function scope applies only to labels. So should not be confused with block scope. The function arguments are treated as if they were declared at the beginning of the block with other variables (remember that the function body is also considered as a block within { }). So the function arguments have block scope (not function scope).
Local scope is general usage to refer the scope that is either function or block scope.
Prototype Scope
They are having the scope only inside the prototype declaration. This scope is interesting because the variable names are valid only in the declaration of prototype and does not conflict with other variable names. It exists for very little time and of less use and so goes unnoticed.
int add(int a, float b);
Here the variables a and b are said to have prototype scope.
Selecting Minimal Scope
When a name has to be resolved, that name is searched in the minimal scope, and if that is not available, it is searched at higher levels of scope. So, if a variable has to be declared, you have to select a minimal scope possible. If you can limit your scope, that increases the efficiency, readability and maintainability of your program. If you want a variable which is not useful outside a block, declare it inside the block and not in the outer ones. Similarly, if you want a variable whose value will be accessed only within the function but has to retain the value between the function calls, opt for static variable to a global one.
I'd say you are introducing a new local scope, or a nested scope, or a block.
This becomes seriously important in C++ when you take active advantage of this:
{
std::lock_guard<std::mutex> lk(my_mutex);
do_critical_stuff(); // might throw exception?
}
// the lock is released automagically!
But even in C it's good practice to only use variables locally where they're needed and not bleed them into unnecessarily wide scopes.
The term is the scope.
K&R2 defines the word scope as
A name also has a scope, which is the region of the program in which
it is known
Scope is the word that refers to the visibility of an identifier.

Where you can and cannot declare new variables in C?

I heard (probably from a teacher) that one should declare all variables on top of the program/function, and that declaring new ones among the statements could cause problems.
But then I was reading K&R and I came across this sentence: "Declarations of variables (including initializations) may follow the left brace that introduces any compound statement, not just the one that begins a function". He follows with an example:
if (n > 0){
int i;
for (i=0;i<n;i++)
...
}
I played a bit with the concept, and it works even with arrays. For example:
int main(){
int x = 0 ;
while (x<10){
if (x>5){
int y[x];
y[0] = 10;
printf("%d %d\n",y[0],y[4]);
}
x++;
}
}
So when exactly I am not allowed to declare variables? For example, what if my variable declaration is not right after the opening brace? Like here:
int main(){
int x = 10;
x++;
printf("%d\n",x);
int z = 6;
printf("%d\n",z);
}
Could this cause trouble depending on the program/machine?
I also often hear that putting variables at the top of the function is the best way to do things, but I strongly disagree. I prefer to confine variables to the smallest scope possible so they have less chance to be misused and so I have less stuff filling up my mental space in each line on the program.
While all versions of C allow lexical block scope, where you can declare the variables depends of the version of the C standard that you are targeting:
C99 onwards or C++
Modern C compilers such as gcc and clang support the C99 and C11 standards, which allow you to declare a variable anywhere a statement could go. The variable's scope starts from the point of the declaration to the end of the block (next closing brace).
if( x < 10 ){
printf("%d", 17); // z is not in scope in this line
int z = 42;
printf("%d", z); // z is in scope in this line
}
You can also declare variables inside for loop initializers. The variable will only exist only inside the loop.
for(int i=0; i<10; i++){
printf("%d", i);
}
ANSI C (C90)
If you are targeting the older ANSI C standard, then you are limited to declaring variables immediately after an opening brace1.
This doesn't mean you have to declare all your variables at the top of your functions though. In C you can put a brace-delimited block anywhere a statement could go (not just after things like if or for) and you can use this to introduce new variable scopes. The following is the ANSI C version of the previous C99 examples:
if( x < 10 ){
printf("%d", 17); // z is not in scope in this line
{
int z = 42;
printf("%d", z); // z is in scope in this line
}
}
{int i; for(i=0; i<10; i++){
printf("%d", i);
}}
1 Note that if you are using gcc you need to pass the --pedantic flag to make it actually enforce the C90 standard and complain that the variables are declared in the wrong place. If you just use -std=c90 it makes gcc accept a superset of C90 which also allows the more flexible C99 variable declarations.
missingno covers what ANSI C allows, but he doesn't address why your teachers told you to declare your variables at the top of your functions. Declaring variables in odd places can make your code harder to read, and that can cause bugs.
Take the following code as an example.
#include <stdio.h>
int main() {
int i, j;
i = 20;
j = 30;
printf("(1) i: %d, j: %d\n", i, j);
{
int i;
i = 88;
j = 99;
printf("(2) i: %d, j: %d\n", i, j);
}
printf("(3) i: %d, j: %d\n", i, j);
return 0;
}
As you can see, I've declared i twice. Well, to be more precise, I've declared two variables, both with the name i. You might think this would cause an error, but it doesn't, because the two i variables are in different scopes. You can see this more clearly when you look at the output of this function.
(1) i: 20, j: 30
(2) i: 88, j: 99
(3) i: 20, j: 99
First, we assign 20 and 30 to i and j respectively. Then, inside the curly braces, we assign 88 and 99. So, why then does the j keep its value, but i goes back to being 20 again? It's because of the two different i variables.
Between the inner set of curly braces the i variable with the value 20 is hidden and inaccessible, but since we have not declared a new j, we are still using the j from the outer scope. When we leave the inner set of curly braces, the i holding the value 88 goes away, and we again have access to the i with the value 20.
Sometimes this behavior is a good thing, other times, maybe not, but it should be clear that if you use this feature of C indiscriminately, you can really make your code confusing and hard to understand.
If your compiler allows it then its fine to declare anywhere you want. In fact the code is more readable (IMHO) when you declare the variable where you use instead of at the top of a function because it makes it easier to spot errors e.g. forgetting to initialize the variable or accidently hiding the variable.
A post shows the following code:
//C99
printf("%d", 17);
int z=42;
printf("%d", z);
//ANSI C
printf("%d", 17);
{
int z=42;
printf("%d", z);
}
and I think the implication is that these are equivalent. They are not. If int z is placed at the bottom of this code snippet, it causes a redefinition error against the first z definition but not against the second.
However, multiple lines of:
//C99
for(int i=0; i<10; i++){}
does work. Showing the subtlety of this C99 rule.
Personally, I passionately shun this C99 feature.
The argument that it narrows the scope of a variable is false, as shown by these examples. Under the new rule, you cannot safely declare a variable until you have scanned the entire block, whereas formerly you only needed to understand what was going on at the head of each block.
Internally all variables local to a function are allocated on a stack or inside CPU registers, and then the generated machine code swaps between the registers and the stack (called register spill), if compiler is bad or if CPU doesn't have enough registers to keep all the balls juggling in the air.
To allocate stuff on stack, CPU has two special registers, one called Stack Pointer (SP) and another -- Base Pointer (BP) or frame pointer (meaning the stack frame local to the current function scope). SP points inside the current location on a stack, while BP points to the working dataset (above it) and the function arguments (below it). When function is invoked, it pushes the BP of the caller/parent function onto the stack (pointed by SP), and sets the current SP as the new BP, then increases SP by the number of bytes spilled from registers onto stack, does computation, and on return, it restores its parent's BP, by poping it from the stack.
Generally, keeping your variables inside their own {}-scope could speedup compilation and improve the generated code by reducing the size of the graph the compiler has to walk to determine which variables are used where and how. In some cases (especially when goto is involved) compiler can miss the fact the variable wont be used anymore, unless you explicitly tell compiler its use scope. Compilers could have time/depth limit to search the program graph.
Compiler could place variables declared near each other to the same stack area, which means loading one will preload all other into cache. Same way, declaring variable register, could give compiler a hint that you want to avoid said variable being spilled on stack at all costs.
Strict C99 standard requires explicit { before declarations, while extensions introduced by C++ and GCC allow declaring vars further into the body, which complicates goto and case statements. C++ further allows declaring stuff inside for loop initialization, which is limited to the scope of the loop.
Last but not least, for another human being reading your code, it would be overwhelming when he sees the top of a function littered with half a hundred variables declarations, instead of them localized at their use places. It also makes easier to comment out their use.
TLDR: using {} to explicitly state variables scope can help both compiler and human reader.
With clang and gcc, I encountered major issues with the following.
gcc version 8.2.1 20181011
clang version 6.0.1
{
char f1[]="This_is_part1 This_is_part2";
char f2[64]; char f3[64];
sscanf(f1,"%s %s",f2,f3); //split part1 to f2, part2 to f3
}
neither compiler liked f1,f2 or f3, to be within the block. I had to relocate f1,f2,f3 to the function definition area.
the compiler did not mind the definition of an integer with the block.
As per the The C Programming Language By K&R -
In C, all variables must be declared before they are used, usually at the
beginning of the function before any executable statements.
Here you can see word usually it is not must..

Resources