Thread: Defining variables in C++ as late as possible?

  1. #1
    Registered User
    Join Date
    May 2013
    Posts
    228

    Defining variables in C++ as late as possible?

    Hi.
    Here's a quote from C++ Primer - Fifth Edition:
    Advice: Define Variables Where You First Use Them

    It is usually a good idea to define an object near the point at which the
    object is first used. Doing so improves readability by making it easy to find
    the definition of the variable. More importantly, it is often easier to give the
    variable a useful initial value when the variable is defined close to where it is
    first used.
    While I can see why that kind of practice is beneficial (defining variables as late as possible, besides what the book pointed out,
    also minimizes their scope, and consequently reducing bugs potential - at least that's my take on it),
    I don't understand why in C, in a course I took a couple of years ago, I was encouraged to do the opposite - "define any variable you'll use in advance,
    at the head of the function body".
    Is there some performance advantage in C when defining variables in advance, that doesn't exist in C++?
    Or maybe I was provided with misinformation in that course?
    Last edited by Absurd; 09-15-2014 at 04:31 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > I was encouraged to do the opposite - "define any variable you'll use in advance, at the head of the function body".
    The problem is that historically (prior to C99), that was your only choice.
    If you want to retain maximum compiler compatibility, then you have to declare all your function variables at the start of a block.

    You can mimic C++ / C99 behaviour by placing declarations / code inside additional open/close brace pairs.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Did you have to do it in the beginning because of how the stack works? That when you're switching stack frames all the allocations are made at once in the very beginning? So before compilers were smart enough to parse a file for all stack-based declarations, it was simplest to just have the user put them all in the same section.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Did you have to do it in the beginning because of how the stack works?
    That may have been part of the reason, but it may also have been because the original authors just liked to have the variables defined before anything else was done. But the first compilers were probably heavily influenced by the assemblers they were currently using.

    Jim

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by MutantJohn View Post
    Did you have to do it in the beginning because of how the stack works?
    That's not how the stack works.
    To be fair, the stack works differently in different operating systems, but the generally known approach I can describe.
    Typically, the stack is implemented somewhere in memory with a specific register pointing to the top of the stack.
    To place a variable on the stack, you either:
    - Use dedicated instructions such as push, or
    - Use general instructions such as mov to move data to a specific offset of the memory as pointed to by the stack pointer register.
    To reserve space, you usually simply subtract a constant to the stack pointer register. To deallocate, you just add a constant.
    This implies that you can just use an add instruction or push instruction at any time to put new stuff on the stack or remove stuff.
    The stack is not some fixed thing that is created at the beginning of a function from a processor's point of view.
    However, due to optimizations, compilers often reserve the necessary stack space at the top of a function and deallocates it at the end.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    I want to agree with you, Elysia but I swear to God, one time I was talking about temporal locality in the cache and that's why declaring variables as you use need them is superior (for better coherency) and phantom told me that wasn't true because it was all allocated upon shifting stack frames.

  7. #7
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Quote Originally Posted by Absurd View Post
    Hi.
    Here's a quote from C++ Primer - Fifth Edition:


    While I can see why that kind of practice is beneficial (defining variables as late as possible, besides what the book pointed out,
    also minimizes their scope, and consequently reducing bugs potential - at least that's my take on it),
    I don't understand why in C, in a course I took a couple of years ago, I was encouraged to do the opposite - "define any variable you'll use in advance,
    at the head of the function body".
    Is there some performance advantage in C when defining variables in advance, that doesn't exist in C++?
    Or maybe I was provided with misinformation in that course?
    I disagree. If I run across a variable halfway down the page of code and it's not its first use, how do I know where its definition is? I have to search all through the code up to that point to find the definition. By that time I've lost the train I was riding. It's better IMO to use the C way. You always know where the definitions are for a quick refresh.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by WaltP View Post
    I disagree. If I run across a variable halfway down the page of code and it's not its first use, how do I know where its definition is? I have to search all through the code up to that point to find the definition. By that time I've lost the train I was riding. It's better IMO to use the C way. You always know where the definitions are for a quick refresh.
    You use your IDE's go to definition feature. It will helpfully open a new little window inside your first showing you the definition. But then again, why do you need to see the definition? All you really need to know is its type.
    Besides, we all know that we should, if possible, not reuse variables. Compilers don't like it. And apparently, according to you, we don't like it, either.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by Elysia View Post
    we should, if possible, not reuse variables. Compilers don't like it.
    I've never heard that before. Do compilers have a harder time optimizing code if a variable is reused multiple times?

    I'll give you a real-life example of something that I do:

    I often declare an int called "bytes" to store the return value of send() and recv(). My code first reads a few bytes from the socket to determine the total length of the message, and then reads the whole message in a loop. Are you saying it's bad to use the same "bytes" variable in the loop that I used previously when I read the message length?
    What can this strange device be?
    When I touch it, it gives forth a sound
    It's got wires that vibrate and give music
    What can this thing be that I found?

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Elkvis View Post
    I've never heard that before. Do compilers have a harder time optimizing code if a variable is reused multiple times?
    Yes, they do. A compiler needs to do a lifecycle analysis to determine how long variables live. If you reuse it elsewhere, then you are artificially "prolonging" said variable's lifetime. The compiler needs to know how long variables live in order to see what variables it can put into registers and when it can reuse said registers. You can look a little on liveness analysis if you're interested.
    Granted, compilers these days are pretty sophisticated, so they can probably break such dependencies, but I have no experience or knowledge of such things.
    So this probably is a "micro optimization" (given that caches exist if the compiler can't break the dependency chain).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User antred's Avatar
    Join Date
    Apr 2012
    Location
    Germany
    Posts
    257
    If you're actually worried about not being able to quickly glance where a local variable is initialized, that's a sure indicator that your function is too long. Time for some refactoring. Break it down into several smaller sub functions.

  12. #12
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by MutantJohn View Post
    Did you have to do it in the beginning because of how the stack works? That when you're switching stack frames all the allocations are made at once in the very beginning? So before compilers were smart enough to parse a file for all stack-based declarations, it was simplest to just have the user put them all in the same section.
    Yeah, that's pretty much it.

    Quote Originally Posted by Elysia View Post
    That's not how the stack works.
    To be fair, the stack works differently in different operating systems, but the generally known approach I can describe.
    Typically, the stack is implemented somewhere in memory with a specific register pointing to the top of the stack.
    To place a variable on the stack, you either:
    - Use dedicated instructions such as push, or
    - Use general instructions such as mov to move data to a specific offset of the memory as pointed to by the stack pointer register.
    To reserve space, you usually simply subtract a constant to the stack pointer register. To deallocate, you just add a constant.
    This implies that you can just use an add instruction or push instruction at any time to put new stuff on the stack or remove stuff.
    The stack is not some fixed thing that is created at the beginning of a function from a processor's point of view.
    However, due to optimizations, compilers often reserve the necessary stack space at the top of a function and deallocates it at the end.
    It's true that you can push things on the stack in the middle of a function, but then you have to manually keep track of what to pop off at the end of the function, which can be tricky with multiple return points. So usually you would allocate all the stack space at the beginning of the function, and pop it off the stack at the end. That's how you would do it in assembly, and that's how you had to do it in early C.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. defining macros or static variables
    By l2u in forum C++ Programming
    Replies: 15
    Last Post: 08-05-2008, 06:28 AM
  2. Defining Variables
    By Beaner in forum C++ Programming
    Replies: 3
    Last Post: 03-10-2005, 05:50 PM
  3. Late on problem
    By alrate in forum C++ Programming
    Replies: 23
    Last Post: 12-19-2004, 08:37 AM
  4. Something for the late nighters
    By Scourfish in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 01-09-2003, 02:57 PM
  5. Globaly defining variables
    By PaloDeQueso in forum C Programming
    Replies: 5
    Last Post: 03-20-2002, 09:38 PM