Use of braces to mark code segments.

I am experimenting with the use of braces to define segments of code with more granularity than just using braces for if and while blocks.

If I have a long block of code divided into segments by braces (I’ve done this), will variables defined inside the braces be local to the segment? That is, a variable is only used within the block will it be released upon the code exiting the same block?

Thanks for your comments.

Yes.

Yes.
It’s a very quick and simple experiment to perform, if you have any doubts.

I wouldn’t trust it. Some compiler down the line may think,:“Eww, extra braces, lets remove them as a service to our user.”

-jim lee

jimLee:
I wouldn’t trust it. Some compiler down the line may think,:“Eww, extra braces, lets remove them as a service to our user.”

-jim lee

And summon the ire of K&R (peace be upon them)?

I don’t think so

jimLee: I wouldn't trust it. Some compiler down the line may think,:"Eww, extra braces, lets remove them as a service to our user."

-jim lee

No, such a compiler would fail a massive slew of test-cases. Compilers don't work like that, they handle the structure of the code directly, after parsing.

djsfantasi: I am experimenting with the use of braces to define segments of code with more granularity than just using braces for if and while blocks.

If I have a long block of code divided into segments by braces (I’ve done this), will variables defined inside the braces be local to the segment? That is, a variable is only used within the block will it be released upon the code exiting the same block?

Thanks for your comments.

While this works, actually doing so would be a good example of a code smell.

If you really have a good reason for doing something like you describe then it is most likely that you should have long ago broken that section of code out into a function.

It's good practices to limit the scope of variables as much as possible. I've considered using this technique to take that to the next level, but never bothered to actually do it. The exception is that I've started always putting my case blocks in braces to avoid the annoying "crosses initialization of" error/warning (depending on whether the core uses -fpermissive).

Probably a bad habit, but I've never been too fond of what I call "frivolous functions" (meaning functions that are only called once in the program). My rule is if I use the same code at multiple places in my program, I put it in a function.

Probably a bad habit, but I've never been too fond of what I call "frivolous functions" (meaning functions that are only called once in the program)

Whilst using a function that is only called once within a program may seem frivolous it does provide a way of isolating possibly troublesome code and can help in testing/debugging by, for instance, returning a fixed value. This is particularly helpful if you don't even have the associated hardware needed for the function or suspect that it may be faulty.

Creating a function also allows you to give it a meaningful name, the importance of which should not be underestimated. You cannot do this when using inline code except by using comments, or if you are desperate, by using labels

I really don't like long or complex functions. Generally, I want a function to be small enough to be all in view in whatever editor I'm using. Also, if it has more than three control constructs, it's too complicated to take in at a glance.

So I'll happily split some of it out into a "frivolous function". Also, as UKHeliBob mentions, you get to give that thing a name, which has great value by itself.

If a function just initializes things for some reason, I'm not going to split it just because it's long but aside from that I can't off-hand think of any other exceptions.

UKHeliBob: Whilst using a function that is only called once within a program may seem frivolous it does provide a way of isolating possibly troublesome code and can help in testing/debugging by, for instance, returning a fixed value.

That's a good point. I find myself frequently creating "frivolous functions" in my Python code for the sake of unit testing. I haven't managed to get into unit testing of my Arduino code yet so that hasn't been a consideration. Of course, I suppose I could consider the use of the code in the main Python script as well as the unit test to make the function no longer technically fall into my definition of "frivolous".

UKHeliBob: You cannot do this when using inline code except by using comments

Yeah, I just use a comment and a blank line above and below to break up the code into its functional parts.

wildbill: I want a function to be small enough to be all in view in whatever editor I'm using. Also, if it has more than three control constructs, it's too complicated to take in at a glance.

My feeling is the need to go hunt down the definition of the frivolous functions that are called to see its code negates those benefits.

I was also influenced to avoid "frivolous functions" in my early programming days by discovering the overhead of function calls. I later discovered I could avoid that by declaring my functions static, and further down the line the improvement in the compiler optimization (LTO I believe) made even that unnecessary. But before either of those things came about the habit had already set in.

Thanks for the input everyone!

I thought of using this technique because I have multiple instances of large blocks of code, in which a small amount of memory is used for local variables. The many places this occurs, eats up s lot of my memory space.

In that case, a function might look attractive. But due to memory localization, I’d have to pass 8-12 arguments to the function, of a variety of variable types. String, long, int (scalar and array), etc...

It doesn’t seem to me that saving the bytes for temporary variables is worth the effort to identify (and duplicate) the memory fit the parameters.

Or I could be wrong. That’s why I asked here.

I'd have to pass 8-12 arguments to the function

Another code smell.

I’m not picking on you there. The day I learned the term “code smell” and searched it I ended up spending two or three nights just reading pages listing them and explaining them and googling the terms I didn’t understand.

I ended up learning more from that one exercise than probably anything I’ve ever done in my life when it comes to coding. I learned a lot of not only the how but also the why to how to structure code well so you can keep working on it in the future.

Highly recommend. It changed the way I code.

djsfantasi: If I have a long block of code divided into segments by braces (I’ve done this), will variables defined inside the braces be local to the segment? That is, a variable is only used within the block will it be released upon the code exiting the same block?

The NAMES will be local to the block in which they are defined. The memory space is allocated when the function is entered and released when the function exits. In other words, no, I don't think the variable will be released when exiting the block. Easy enough to test:

extern unsigned int __heap_start;
extern void *__brkval;


/*
   The free list structure as maintained by the
   avr-libc memory allocation routines.
*/
struct __freelist
{
  size_t sz;
  struct __freelist *nx;
};


/* The head of the free list structure */
extern struct __freelist *__flp;


/* Calculates the size of the free list */
int freeListSize()
{
  struct __freelist* current;
  int total = 0;
  for (current = __flp; current; current = current->nx)
  {
    total += 2; /* Add two bytes for the memory block's header  */
    total += (int) current->sz;
  }
  return total;
}


int freeMemory()
{
  int free_memory;
  if ((int)__brkval == 0)
  {
    free_memory = ((int)&free_memory) - ((int)&__heap_start);
  }
  else
  {
    free_memory = ((int)&free_memory) - ((int)__brkval);
    free_memory += freeListSize();
  }
  return free_memory;
}


void test()
{
  Serial.print("Entered test().  Free memory = ");
  Serial.println(freeMemory());
  {
    char UseUpMemory[100] = "This block uses 100 bytes";
    Serial.print("Entered first block.  Free memory = ");
    Serial.println(freeMemory());
    Serial.println(UseUpMemory);
  }
  Serial.print("Exited first block.  Free memory = ");
  Serial.println(freeMemory());
  {
    char UseUpMemory[300] = "This block uses 300 bytes";
    Serial.print("Entered second block.  Free memory = ");
    Serial.println(freeMemory());
    Serial.println(UseUpMemory);
  }
  Serial.print("Exited second block.  Free memory = ");
  Serial.println(freeMemory());
}


void setup()
{
  Serial.begin(115200);
  while (!Serial);


  Serial.print("In Setup() before test().  Free memory = ");
  Serial.println(freeMemory());


  test();


  Serial.print("In Setup() after test().  Free memory = ");
  Serial.println(freeMemory());
}


void loop() {}

The results show that enough memory for the block with the most locals is allocated when the function is entered and is released when the function exits.

In Setup() before test().  Free memory = 1186
Entered test().  Free memory = 882
Entered first block.  Free memory = 882
This block uses 100 bytes
Exited first block.  Free memory = 882
Entered second block.  Free memory = 882
This block uses 300 bytes
Exited second block.  Free memory = 882
In Setup() after test().  Free memory = 1186

In this case, the function call uses 4 bytes and the 300 bytes of local array in the second block is shared by the 100 bytes of local array in the first block.