I am learning C using the books listed here. My question is that is there a difference between a variable and an object. Consider the following example:
int i = 0; //i is an object of type int. Or we can say i is a variable of type int
int &refI = i; //refI is a "reference variable" of "reference type `int&`. But here refI is not an object.
My current understanding is that both of the terms variable and object overlaps to a large extent. But in some contexts like in case of refI
above, there can be some differences. In particular, refI
is a reference variable of reference type int&
and refI
is not an object because a reference is an alias for some other object. While i
is both an object and a variable.
My question is that am i correctly analyzing the refI
case above? If not, what does the standard say about this.
My second question is that, does the standard C strictly differentiate between these two terms. If yes, how and where. For example something like, a variable may be defined as an object with a name. And any object without a name is not a variable.
Here the user says that a variable and object are different.
CodePudding user response:
Difference between an object and a variable in C
Variable is a programming language level concept. A variable has a type and it (usually) has a name. A variable can denote an object, or a reference.
There's no concise definition for the meaning of "variable" in the standard nor a section dedicated to them alone, but closest individual rule to specifying its meaning is:
[basic.pre]
A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object.
Object is a concept in the level of the abstract machine that the language defines. It is mostly specified in the section "Object model [intro.object]" which begins:
[intro.object]
The constructs in a C program create, destroy, refer to, access, and manipulate objects. An object is created by a definition, by a new-expression ([expr.new]), by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created ([conv.rval], [class.temporary]). An object occupies a region of storage in its period of construction ([class.cdtor]), throughout its lifetime, and in its period of destruction ([class.cdtor]).
int i = 0; //i is an object of type int. Or we can say i is a variable of type int
i
is a variable of type int
. The variable's name denotes an object.
int &refI = i; //refI is a "reference variable" of "reference type `int&`. But here refI is not an object.
refI
is a variable of type int&
. The variable's name denotes a reference. The reference is bound to the object named by i
and can be seen as another name for the same object.
CodePudding user response:
Your understanding seems to be correct. I'm going to reuse the quote from @RichardCritten answer, but with a different explanation.
A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object.
So a variable is one of:
- A named object, e.g.
int i = 1;
. Non-static data members don't count. Functions don't count, since they're not objects, see below. Named objects are always created by declarations. - An unnamed object that has a declaration. The only ones I'm aware of are unnamed function parameters (and structured bindings, see below).
- A named reference, e.g.
int &j = i;
. Non-static data members don't count. Named references are always created by declarations. - An unnamed reference that has a declaration. The only ones I'm aware of are unnamed function parameters (and structured bindings, see below). As far as I'm aware, there are no unnamed references without declarations, since expressions can't have reference types.
- A structured binding: there's a single unnamed object or reference per structured binding (regardless of the number of identifiers), AND, if this structured binding was initialized with a
std::tuple
-like class (as opposed to an array or a class with magically detected members), there's also one reference per each member (unnamed, surprisingly - the identifiers magically refer to those references, they are not their names).
The constructs in a C program create, destroy, refer to, access, and manipulate objects. An object is created by a definition, by a new-expression, by an operation that implicitly creates objects (see below), when implicitly changing the active member of a union, or when a temporary object is created. An object occupies a region of storage in its period of construction, throughout its lifetime, and in its period of destruction.
[Note 1: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. — end note]
The properties of an object are determined when the object is created. An object can have a name. An object has a storage duration which influences its lifetime. An object has a type.
The above explains what counts as an object.
But I find it easier to remember what isn't one:
- Functions are not objects. (see quote above)
- References are not objects. (again, note that expressions can't have reference types; there are no temporary unnamed references)
- Prvalues are not objects (since C 17).
- If the "object" doesn't exist, it isn't an object (i.e. if its lifetime hasn't started or has already ended, AND its constructor nor destructor are currently running).
- Obviously, labels are not objects, and neither are macros.
CodePudding user response:
Current Draft Standard basic.pre.6 "A variable is introduced by the declaration of a reference other than a non-static data member or of an object. The variable's name, if any, denotes the reference or object."