0

I understand what scope and lifetime are and how they're different:

Scope: the visibility of a variable i.e. which blocks of code can reference that variable

Lifetime: how a long a variable's value will be retained in memory

My question is: in the picture below, on what basis did we decide that the variable x has a lifetime and not scope, and variable b1 has a scope but no lifetime?

enter image description here

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63

2 Answers2

1

In the C example, the static keyword keeps the variable x in memory for future function calls. But that doesn't mean that you can access x from outside that function (like it's trying to do in main). So you have a variable in memory (lifetime) but can't access it from outside the function (no scope)

In the java example, an object reference is declared, but no object is ever created. So you can access the reference (you have scope) but no object in memory (no lifetime)

Fred
  • 1,462
  • 8
  • 15
  • In Java, what about `Book b1;` creates a reference rather than an object of type `b1`? And, if it does create a reference, why do we not say that the reference has a lifetime, even if it is not yet associated with an object to which it refers? Is not the reference itself an entity that is created at some time, takes on certain values/associations with objects to which it refers, and is destroyed? – Eric Postpischil Mar 06 '18 at 14:53
  • You are right that a reference to `null` is pushed to the local variable array. The local variable array has the same lifetime as the method execution, so indeed the null reference might be considered to have a 'lifetime'. Actual objects go to the heap instead and they have variable lifetimes. So if you put it like that then it is kind of hard to know where to draw the line, specially if you consider primitive types to have lifetime (since they live in the local variables array too) – Fred Mar 06 '18 at 15:44
  • But again... `null` is not an object nor a type. It's a special constant. So I wouldn't say it has a formal lifetime, because it's not a variable at all – Fred Mar 06 '18 at 15:45
  • The `null` "reference" in this case would pretty much consist of a local variable table entry, with the variable name, index, length etc., and a constant in the local variable array. All this would be hardcoded into the jvm bytecode – Fred Mar 06 '18 at 15:49
  • tl;dr, I'm sure the author of that image didn't take all this info into consideration. As you probably shouldn't lol – Fred Mar 06 '18 at 15:51
0

[The question is tagged with both Java and C. This answer addresses C. The information here is taken from draft N1570 of the C 2011 standard.]

A variable consists of both an identifier (the name by which it is known) and an object (the storage in memory that holds its value).

The identifier always has some scope, and the object always has some lifetime. (When memory is allocated with malloc, the storage has lifetime, but there is no identifier, so there is no scope for a name.)

For a variable, the scope of its identifier is determined by where its declaration is in the source code?

  • If the declaration is outside any block (a sequence of statements and declarations inside '{' and '}'), it has file scope, and the identifier is visible from the declaration to the end of the translation unit (the source code after preprocessing is done).
  • If the declaration is inside a block or inside the parameter declarations of a function definition (not just a declaration), it has block scope, and the identifier is visible from its declaration to the end of the block.
  • If the declaration is inside the parameter declarations of a function declaration that is not a definition, it has function prototype scope, and is visible from its declaration to the end of the function declarator.

There are other identifiers besides variable identifiers. The rules for identifiers of functions; tags for structures, unions, and enumerations; and typedef names are the same as for variable identifiers. For labels (used in goto statements, written as label:), the identifier has function scope, and it is visible everywhere in the function in which it appears.

There are four storage durations, also called lifetimes: static, thread, automatic, and allocated. The storage duration of an object is affected by the linkage of its identifier, so we need to discuss linkage first. Linkage is a way of making the same identifier in different scopes refer to the same object.

  • If an identifier for an object or a function at file scope is declared with static, it has internal linkage. Internal linkage means that any other declarations in the same translation unit will refer to the same object or function.

  • If an identifier is declared with extern, the linkage depends on whether there is already a prior declaration visible:

    1. If no prior declaration is visible, the identifier has external linkage. This means any other declarations in the program will refer to the same object or function.

    2. If there is a prior declaration, and it specifies internal or external linkage, the linkage for the current declaration is the same as the prior declaration.

    3. If there is a prior declaration but it does not specify any linkage, the linkage for the current declaration is external.

  • If a function is declared with no storage-class specifier (typedef, extern, static, _Thread_local, auto, or register), its linkage is as if it were declared with extern (so it follows the rule above about depending on a prior declaration).

  • If an object is declared at file scope with no storage-class specifier, its linkage is external.

  • Otherwise, the identifier has no linkage, so each declaration of it refers to a different entity. This includes an identifier of anything that is not an object or a function (such as a structure tag or a typedef name), a function parameter, and variables declared inside functions without extern.

Now we can state the rules for storage durations:

  • If an object is declared with static and without _Thread_local, it has static storage duration, and its lifetime is the entire execution of the program.

  • If an object is declared without _Thread_local and has external or internal linkage, it has static storage duration.

  • If an object is declared with _Thread_local, it has thread storage duration, and its lifetime is the entire execution of the thread for which is is created.

  • If an object is declared without static and with no linkage, it has automatic storage duration. If it is not a variable length array, its lifetime is from when execution enters the block it is in until execution of that block ends. (Note that calling a function suspends execution of a block but does not end it.) If it is a variable length array, its lifetime is from when execution reaches the declaration until execution leaves the scope of the declaration.

There is also an allocated storage duration for objects created by routines in the malloc family, and there is a temporary lifetime that applies to objects created within expressions, but I omit discussion of those since they are not relevant to declarations of named objects.

As you can see, the rules are somewhat complicated. However, you will come to recognize the scopes and lifetimes with practice.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312