C objects

S

Stefan Ram

RCollins said:
Since you are calling main() recursively, aren't you actually
creating 3 different i's? Each i is _not_ the same, even though
they happen to have the same name.

Yes, one can see it this way.

Actually it depends on the mode of speech:

"Ronald" is a name.
Ronald is a person.
While there are more Ronalds than one Ronald, there is still
only one name "Ronald", but there are several Ronalds.

In the source code, there is exactly one identifier "i".
Executing the program does not change the number of "i"s in
the source code. The identifier "i" is a ("static") entity of
the source code model. An object is a ("dynamic") entity of
the execution model. How these models relate to each other is
being described by the C language specification.
"Bound"? I don't know what that means in C (although I understand
the concept from ProLog).

The specification in fact does not use this wording.

I am using the term "binding" to refer to a relation between
an identifier (as an element of the source code model) to an
object (as an element of the execution model). ISO/IEC 9899:1999
(E) uses wording such as "denotes", "designates" or "refers".
In this case, your example seems very
compiler-specific (or perhaps, optimization-specific). The compiler
is perfectly free to allocate memory storage to i, even if it is
never used to store a value. That would make i an object, regardless
of what (if anything) is stored in it.

Usually an "activation record" is created, when a function is
being executed, often on the "stack". The automatic variables
and parameter variables are bound to storage in this
"activation record". When a function is not being activated,
it would make no sense to create such an activation record,
although I can not exclude that some compiler might create
code to do so, but this would at least partially execute
a function, which is never called.
 
K

Keith Thompson

Yes.
(An approximate meaning might be derived from those uses.)

All the uses in the standard refer to individual declared objects.
There aren't nearly enough to infer whether the term refers *only* to
individual declared objects.
I would not call it a variable. Obviously, it is an expression.

It's an expression that refers to an object (assuming there's actually
an object at the address to which ptr points). The question was
whether that object is a "variable" (likewise for array elements,
struct members, and so forth), or whether the term only refers to
declared named objects.

There is no answer to this question. Given a declaration like
"int i;", we can safely refer to i as a "variable"; for more complex
cases, we should stick to the more formal term "object".
 
K

Keith Thompson

E. Robert Tisdale said:
No.

malloc() doesn't create objects.
It returns a pointer of type void*.
A data object must be initialized to a valid value
of an object of that type before you can call it an object --
it must be constructed.

C99 3.14 defines the term "object":

object

region of data storage in the execution environment, the contents
of which can represent values

The term "object" refers to the *region*, not to the data it may
contain.
 
E

E. Robert Tisdale

Keith said:
C99 3.14 defines the term "object":

object

region of data storage in the execution environment,
the contents of which can represent values

The term "object" refers to the *region*,
not to the data it may contain.

It *must* be an object of some type.
The type specifies *all* of the values that that object may have.
 
E

E. Robert Tisdale

Mike said:
E. Robert Tisdale said:
A data object must be initialized to a valid value
of an object of that type before you can call it an object --

Not true.
it must be constructed.

"Constructed" doesn't have a meaning in C.

int main(int argc, char* argv[]) {
int i; // is 'i' an object? The language standard says it is
return 0;
}

Whatever value 'i' has must be a valid int.

typedef struct X {
int* p;
} X;

int main(int argc, char* argv[]) {
X x; // is 'x' a valid object?
return 0;
}
 
R

RCollins

Stefan said:
Yes, one can see it this way.

Actually it depends on the mode of speech:

"Ronald" is a name.
Ronald is a person.
While there are more Ronalds than one Ronald, there is still
only one name "Ronald", but there are several Ronalds.

In the source code, there is exactly one identifier "i".
Executing the program does not change the number of "i"s in
the source code. The identifier "i" is a ("static") entity of
the source code model. An object is a ("dynamic") entity of
the execution model. How these models relate to each other is
being described by the C language specification.

So, by this reasoning, then the 2 functions (in the same source
file) below:

void foo(void) {
int i;
i = 1;
}

void bar(void) {
int i;
i = 2;
}

define only 1 identifier, that happens to have 2 different
object locations?
The specification in fact does not use this wording.

I am using the term "binding" to refer to a relation between
an identifier (as an element of the source code model) to an
object (as an element of the execution model). ISO/IEC 9899:1999
(E) uses wording such as "denotes", "designates" or "refers".




Usually an "activation record" is created, when a function is
being executed, often on the "stack". The automatic variables
and parameter variables are bound to storage in this
"activation record". When a function is not being activated,
it would make no sense to create such an activation record,
although I can not exclude that some compiler might create
code to do so, but this would at least partially execute
a function, which is never called.

I don't think we're on the same wavelength at all. We're (or, at
least, I) are not talking about what happens at run-time. We're
talking about source code (the only part we have any real control
over).

in the simple function:

void foo(void) {
int i;
}

the identifer i refers to an object of type integer; if I never use
the variable, or if foo() is explicitly never called, then the
compiler may choose to optimize it away. But, as far as my (source)
program is concerned, both foo() and i exist, and refer to somthing
concrete.
 
R

RCollins

E. Robert Tisdale said:
Mike said:
E. Robert Tisdale said:
A data object must be initialized to a valid value
of an object of that type before you can call it an object --


Not true.
it must be constructed.


"Constructed" doesn't have a meaning in C.

int main(int argc, char* argv[]) {
int i; // is 'i' an object? The language standard says it is
return 0;
}


Whatever value 'i' has must be a valid int.

typedef struct X {
int* p;
} X;

int main(int argc, char* argv[]) {
X x; // is 'x' a valid object?
return 0;
}

Sure, X is a valid object; it is a structure containing a pointer.
Since it is never used, the compiler may choose to optimize it
away, but as far as your source code is concerned, it is a real thing.
 
P

pete

E. Robert Tisdale said:
It *must* be an object of some type.
The type specifies *all* of the values that that object may have.

Keith Thompson is right and you are completely wrong.

N869
6.2.5 Types
[#1] The meaning of a value stored in an object or returned
by a function is determined by the type of the expression
used to access it. (An identifier declared to be an object
is the simplest such expression; the type is specified in
the declaration of the identifier.)

If you have
signed char Integer = -1;
then Integer is less than zero.
but (*(unsigned char *)&Integer) is a positive value
and there's only one object under discusion there.
The statement
--*(unsigned char *)&Integer;
decrements an object of type unsigned char.
 
S

Stefan Ram

RCollins said:
So, by this reasoning, then the 2 functions (in the same source
file) below:
void foo(void) {
int i;
i = 1;
}
void bar(void) {
int i;
i = 2;
}
define only 1 identifier, that happens to have 2 different
object locations?

Yes, just let me quote ISO/IEC 9899:1999 (E):

"For each different entity that an identifier designates,
the identifier is visible (i.e., can be used) only
within a region of program text called its scope."

Note the singular "an identifier". "An identifier" (i.e., only
1 identifier) might designate different entities. This is the
wording of ISO/IEC 9899:1999 (E).

Another reason: An identifier is a lexical concept and is
defined as:

(6.4.2.1) identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit

So by this extensional definition, there exist only one
identifier "i".
I don't think we're on the same wavelength at all. We're (or, at
least, I) are not talking about what happens at run-time. We're
talking about source code (the only part we have any real control
over).

The source code model does not contain the notion of an
"object". The source code is built of lexical and syntactical
units. An object is part of the execution model, though in
order to interpret (make sense of) the source code, one needs
to mention execution model entities.
in the simple function:
void foo(void) {
int i;
}
the identifer i refers to an object of type integer; if I never use
the variable, or if foo() is explicitly never called, then the
compiler may choose to optimize it away. But, as far as my (source)
program is concerned, both foo() and i exist, and refer to somthing
concrete.

This is not a mere "optimization". The local variables of a
function are created as many times as the function is
activated at run time - otherwise recursion would not work.
So, if a function is not activated, there is not reason to
create activation records.

The identifier "i" refers to an object under the assumption
that the function is currently activated. This is usually
taken for granted, so that one does not mention it. By
recursion, a function may be activated more than once in the
same program instance at the same time. In this case, when one
speaks about "i" one usually is referring to an exemplary i
from all those is existing at the same time.
 
M

Mike Wahler

E. Robert Tisdale said:
Mike said:
E. Robert Tisdale said:
A data object must be initialized to a valid value
of an object of that type before you can call it an object --

Not true.
it must be constructed.

"Constructed" doesn't have a meaning in C.

int main(int argc, char* argv[]) {
int i; // is 'i' an object? The language standard says it is
return 0;
}

Whatever value 'i' has must be a valid int.

Right. But 'i' isn't required to represent a value.
That's what 'uninitialized' means.
typedef struct X {
int* p;
} X;

int main(int argc, char* argv[]) {
X x; // is 'x' a valid object?

Yes. But it doesn't represent any meaningful value.

-Mike
 
M

Mike Wahler

E. Robert Tisdale said:
It *must* be an object of some type.
The type specifies *all* of the values that that object may have.

Note that it's. "May", not "must". Verbatim from the standard:
"can represent values." When the standard means "must", it
says "must". Here, it does not.

-Mike
 
R

RCollins

Stefan said:
Yes, just let me quote ISO/IEC 9899:1999 (E):

"For each different entity that an identifier designates,
the identifier is visible (i.e., can be used) only
within a region of program text called its scope."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Notice the part that I underlined. This would tell me that the
var i inside foo() is different than the var i inside bar(); they
just happen to have the same name.
Note the singular "an identifier". "An identifier" (i.e., only
1 identifier) might designate different entities. This is the
wording of ISO/IEC 9899:1999 (E).

Another reason: An identifier is a lexical concept and is
defined as:

(6.4.2.1) identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit

So by this extensional definition, there exist only one
identifier "i".

This is just a rule on how to spell identifiers. Let me put this
another way: if I generate a lexical parse tree for the 2 functions
foo() and bar() above, would you expect that the var i appears only
once?
The source code model does not contain the notion of an
"object". The source code is built of lexical and syntactical
units. An object is part of the execution model, though in
order to interpret (make sense of) the source code, one needs
to mention execution model entities.




This is not a mere "optimization". The local variables of a
function are created as many times as the function is
activated at run time - otherwise recursion would not work.
So, if a function is not activated, there is not reason to
create activation records.

Yes, but what has this to do with identifiers or object names?
For the most part, I would not expect an identifier to survive
the compiler ... only references to stack or memory locations.
(There are exceptions, of course, especially if you are generating
debugging code).
The identifier "i" refers to an object under the assumption
that the function is currently activated. This is usually
taken for granted, so that one does not mention it. By
recursion, a function may be activated more than once in the
same program instance at the same time. In this case, when one
speaks about "i" one usually is referring to an exemplary i
from all those is existing at the same time.

So, then, each time a function is called (recursive or not),
you get a new object named "i" (for example) that is different
than any other object named "i".

I think this is what I started out saying several posts ago.
 
S

Stefan Ram

RCollins said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Notice the part that I underlined. This would tell me that the
var i inside foo() is different than the var i inside bar(); they
just happen to have the same name.

As it has been noticed before, "var" is an informal term in C,
so you might use it this way. The notion "the var i" is not
the same notion as the notion "the identifier i", because the
meaning of "identifier" is defined by ISO/IEC 9899:1999 (E).
This is just a rule on how to spell identifiers. Let me put this
another way: if I generate a lexical parse tree for the 2 functions
foo() and bar() above, would you expect that the var i appears only
once?

It is possible that the text "i" is stored only once in the
memory of the parser, when the parse tree actually is a direct
acyclic graph. This is an implementation detail of a parser.
Yes, but what has this to do with identifiers or object names?

It has only to do with identifieres as long as the source
code is taken into consideration.
For the most part, I would not expect an identifier to survive
the compiler ... only references to stack or memory locations.
(There are exceptions, of course, especially if you are generating
debugging code). (...)
So, then, each time a function is called (recursive or not),
you get a new object named "i" (for example) that is different
than any other object named "i".

Independend of the language "C", the identifier "i" and the
meaning of "object": it is part of the meaning of the word
"other", that any object is different than any /other/ object.

What remains is: A single identifier of the source code might
refer to several objects at run time, either by multiple
scopes, or by multiple life-times, or by both.
 
J

Joe Wright

E. Robert Tisdale said:
It *must* be an object of some type.
The type specifies *all* of the values that that object may have.

Please Mr. Tisdale, consider this ..

unsigned int *ui;
ui = malloc(sizeof *ui);

.... Assuming malloc() was successful, is ui[0] an object? Of course
it is. Was it created by the declaration of ui? No, declarations
don't define or create objects. I guess malloc() did it.
 
E

Emmanuel Delahaye

Joe Wright wrote on 08/08/04 :
unsigned int *ui;

This is the defintion of a pointer. It creates statically a 'pointer'
object. Its value is undeterminate (points anywhere).
ui = malloc(sizeof *ui);

This creates dynamically an object which address is stored into the
pointer 'ui'.
... Assuming malloc() was successful, is ui[0] an object? Of course it is.
Yes.

Was it created by the declaration of ui?

What declaration ?
No, declarations don't define or
create objects. I guess malloc() did it.

I think you are mixing declaration and definition. Of course an object
declaration creates nothing, but an object definition does create an
object.

The point is that a pointer is just a few bytes in memory, but it has a
size, type and address. It is an object.
 
K

Keith Thompson

A note to Stefan Ram:

You indent all your new text. Please don't do this; it's confusing.
Indentation usually indicates that you're quoting someone else. New
text should be left-justified, like this.

Thank you.
 
E

E. Robert Tisdale

Mike said:
E. Robert Tisdale said:
Mike said:
E. Robert Tisdale wrote:

A data object must be initialized to a valid value
of an object of that type before you can call it an object --

Not true.

it must be constructed.

"Constructed" doesn't have a meaning in C.

int main(int argc, char* argv[]) {
int i; // is 'i' an object? The language standard says it is
return 0;
}

Whatever value 'i' has must be a valid int.

Right. But 'i' isn't required to represent a value.
That's what 'uninitialized' means.
typedef struct X {
int* p;
} X;

int main(int argc, char* argv[]) {
X x; // is 'x' a valid object?

Yes. But it doesn't represent any meaningful value.

Then your definition of *type* makes no sense.
A type defines *all* of the values that an object may have.
You seem to be saying that an "uninitialized" object
may have [redundant] meaningless values.
By your definition, the values that a type may have
is determined by its representation
which means that data abstraction is not possible in C.

You are interpreting the C standards documents too literally.
And just like the fundamentalists
who interpret Holy Scripture too literally,
you eventually encounter contradictions to logic and common sense.
 
R

RCollins

Stefan said:
As it has been noticed before, "var" is an informal term in C,
so you might use it this way. The notion "the var i" is not
the same notion as the notion "the identifier i", because the
meaning of "identifier" is defined by ISO/IEC 9899:1999 (E).




It is possible that the text "i" is stored only once in the
memory of the parser, when the parse tree actually is a direct
acyclic graph. This is an implementation detail of a parser.




It has only to do with identifieres as long as the source
code is taken into consideration.




Independend of the language "C", the identifier "i" and the
meaning of "object": it is part of the meaning of the word
"other", that any object is different than any /other/ object.

What remains is: A single identifier of the source code might
refer to several objects at run time, either by multiple
scopes, or by multiple life-times, or by both.

While I appreciate your obvious knowledge (and it *is* vast),
I have completely lost track of where *you* stand in all this.

Let me summarize my position:
Across different scopes (or different lifetimes) there may be
multiple objects (variables?) with the same identifier name.
These objects are separate and distinct from each other; the
mere fact that multiple objects have the same identifier name does
not make them the same object. In addition, I feel that an
identifier name declared in two different functions declares two
different identifiers. IOW, the "i" in foo() is a *different*
identifier than the "i" in bar(). (In other languages, this
would be explicitly called out by the full identifier of foo::i
or bar::i). So long as the compiler can tell the difference,
I don't really care how the run-time environment stores them
(or even *if* it stores them).

Now ... what was *your* position again?
 
R

RCollins

E. Robert Tisdale said:
Mike said:
E. Robert Tisdale said:
Mike Wahler wrote:

E. Robert Tisdale wrote:

A data object must be initialized to a valid value
of an object of that type before you can call it an object --


Not true.

it must be constructed.


"Constructed" doesn't have a meaning in C.

int main(int argc, char* argv[]) {
int i; // is 'i' an object? The language standard says it is
return 0;
}


Whatever value 'i' has must be a valid int.


Right. But 'i' isn't required to represent a value.
That's what 'uninitialized' means.
typedef struct X {
int* p;
} X;

int main(int argc, char* argv[]) {
X x; // is 'x' a valid object?


Yes. But it doesn't represent any meaningful value.


Then your definition of *type* makes no sense.
A type defines *all* of the values that an object may have.
You seem to be saying that an "uninitialized" object
may have [redundant] meaningless values.
By your definition, the values that a type may have
is determined by its representation
which means that data abstraction is not possible in C.

I think, in this case, "unitialized" might mean "unknown".
For example:

void foo(void) {
int i; /* uninitialized value here */

printf("i=%d\n", i);
}

(ignoring the undefined behaviour for now) will print
out some unknown decimal value.
 
R

RCollins

Joe said:
E. Robert Tisdale said:
It *must* be an object of some type.
The type specifies *all* of the values that that object may have.


Please Mr. Tisdale, consider this ..

unsigned int *ui;
ui = malloc(sizeof *ui);

... Assuming malloc() was successful, is ui[0] an object? Of course it
is. Was it created by the declaration of ui? No, declarations don't
define or create objects. I guess malloc() did it.

What if *ui (since it is un-initialized) contains a trap representation?
Is it still considered an int object?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
anuragag27

Latest Threads

Top