Standard C library functions in freestanding systems

J

J de Boyne Pollard

M> The library functions which are included to allow process
M> launch, forking, and termination, imply that it is both
M> possible and desirable for a process to fork itself. This is
M> a fundamental part of the Unix thought process, but is
M> not essential for a working OS.

There are no Standard C Library functions for process forking or
overlaying. The fork() and execve() functions are part of the C
language bindings to POSIX. They are not parts of the Standard C
Library.

M> Why should the user have access to memory mapping,
M> allocation and de-allocation routines? [...]

Similarly, mmap() is not a Standard C Library function.

M> What I am trying to say is not that these things are right
M> or wrong, but that the implementation of the functions,
M> and thus the library, pre-supposes that the OS will work
M> in the Unix manner.

The error that you are making in your argument is that it is entirely
circular. You are taking functions from the POSIX C language bindings
and arguing that they pre-suppose a Unix-like operating system. Of
course they do. POSIX is the _definition_ of a Unix-like operating
system. However, you cannot make such an argument based upon
functions from the _Standard C Library_. The Standard C Library does
not either pre-suppose or mandate a Unix-like operating system.
Indeed, freestanding implementations of the C or C++ languages do not
pre-suppose operating systems at all.

M> my point is basically that the C library defines the API of the OS.
This
M> forces the OS to have that API, and this leaves very little leeway
for
M> the OS designer to deviate from another UNIX clone.

That point is wrong, as explained above. The Hurd and Plan 9 are
existence proofs of its incorrectness, as are the many embedded
systems written in the C and C++ languages.
 
R

Rod Pemberton

J de Boyne Pollard said:
The Standard C Library does
not either pre-suppose or mandate a Unix-like operating system.
Indeed, freestanding implementations of the C or C++ languages do not
pre-suppose operating systems at all.

That was exactly Matt's point, if you had been reading the rest of the
a.o.d. thread... Your response seems to be without regard to the context.

He replied to your post, correcting you, but dropped comp.lang.c and
comp.std.misc from the reply.

We were discussing the philosophical, practical issues, and limitations of
application programmers attempting to write applications for a complete
modern OS with C only versus C with the an OS specific library which might
include the standard C library, POSIX library, other OS functionality, or
functionality equivalent to those.


Rod Pemberton
 
R

Rod Pemberton

J de Boyne Pollard said:
M> The library functions which are included to allow process
M> launch, forking, and termination, imply that it is both
M> possible and desirable for a process to fork itself. This is
M> a fundamental part of the Unix thought process, but is
M> not essential for a working OS.

There are no Standard C Library functions for process forking or
overlaying. The fork() and execve() functions are part of the C
language bindings to POSIX. They are not parts of the Standard C
Library.

We were discussing the use of these in OS development. Nowhere did Matt say
they were part of the C library. In regards to the OP's original post,
these would be part of a OS specific library implemented as a DLL. That DLL
may include all of the standard C library, may include all of the POSIX
libraries, and may include various OS specific functionality, or it may not.
The boundaries and scope of what was or wasn't to be included in the
development of the OP's OS DLL wasn't mentioned. Those boundaries were
under discussion.
M> Why should the user have access to memory mapping,
M> allocation and de-allocation routines? [...]

Similarly, mmap() is not a Standard C Library function.

It's true that mmap isn't part of the C library, but what does your response
have to do with an OS controlling various forms of user memory access? OS
development context lost completely...
M> What I am trying to say is not that these things are right
M> or wrong, but that the implementation of the functions,
M> and thus the library, pre-supposes that the OS will work
M> in the Unix manner.

The error that you are making in your argument is that it is entirely
circular.

No, this has nothing to do with the conversation at hand. He was stating
that he didn't want POSIX or C libraries to influence the design of his OS.
He stated that using them in his OS would essentially force him to inherit
some of the concepts behind their design - most of which were due to UNIX,
such as a hierarchical filesystem and the functions or API used to access
the filesystem.
You are taking functions from the POSIX C language bindings
and arguing that they pre-suppose a Unix-like operating system. Of
course they do. POSIX is the _definition_ of a Unix-like operating
system.

No, UNIX is the _definition_ of a Unix-like operating system... POSIX is
the definition of a _portable_ Unix-like operating system.
However, you cannot make such an argument based upon
functions from the _Standard C Library_. The Standard C Library does
not either pre-suppose or mandate a Unix-like operating system.
Indeed, freestanding implementations of the C or C++ languages do not
pre-suppose operating systems at all.

He wasn't. You just restated his point from prior posts. But, he also
wants "advanced" features in his OS such as:
"file I/O, directory management, (non-automatic) memory management, system
clock, process execution, environment, and signals (C interrupts). This
functionality isn't part of the C language. It's part of the C library."
(quoting myself...)
M> my point is basically that the C library defines the API of the OS.
This
M> forces the OS to have that API, and this leaves very little leeway
for
M> the OS designer to deviate from another UNIX clone.

That point is wrong, as explained above. The Hurd and Plan 9 are
existence proofs of its incorrectness, as are the many embedded
systems written in the C and C++ languages.

First, I wasn't talking about embedded systems. I was talking about OSes
sufficiently advanced that applications can be written. "My assumption was
that if someone was writing an application for his OS, that his OS is
running on something powerful enough to have applications written for it,
say a PC or 1U router, and not on something far less powerful, say a Lego
Robot or a 1U digital effects processor. Anything less powerful than a PC
rarely runs more than a single master program." (quoting myself... Yes, I
know there are small devices which do. Please don't post examples.)

Second, I already brought up the issue of hiding the complexity of
implementing different OS concepts behind an existing API. "The question
is: 'Is the new paradigm sufficiently complex that it can't be easily hidden
behind the functions of the old paradigm?'" (quoting myself...) Matt has
yet to provide his thoughts here.


If you'd read the thread,...


Rod Pemberton
 
P

pete

Rod Pemberton wrote:
We were discussing the philosophical,
practical issues, and limitations of
application programmers attempting to
write applications for a complete modern OS
with C only versus C with the an OS specific library
which might include the standard C library,
POSIX library, other OS functionality, or
functionality equivalent to those.

I wrote some math functions in portable freestanding C code.

http://www.mindspring.com/~pfilandr/C/fs_math/
 
M

Matt

Rod said:
J de Boyne Pollard said:
M> The library functions which are included to allow process
M> launch, forking, and termination, imply that it is both
M> possible and desirable for a process to fork itself. This is
M> a fundamental part of the Unix thought process, but is
M> not essential for a working OS.

There are no Standard C Library functions for process forking or
overlaying. The fork() and execve() functions are part of the C
language bindings to POSIX. They are not parts of the Standard C
Library.

We were discussing the use of these in OS development. Nowhere did Matt say
they were part of the C library. In regards to the OP's original post,
these would be part of a OS specific library implemented as a DLL. That DLL
may include all of the standard C library, may include all of the POSIX
libraries, and may include various OS specific functionality, or it may not.
The boundaries and scope of what was or wasn't to be included in the
development of the OP's OS DLL wasn't mentioned. Those boundaries were
under discussion.
M> Why should the user have access to memory mapping,
M> allocation and de-allocation routines? [...]

Similarly, mmap() is not a Standard C Library function.

It's true that mmap isn't part of the C library, but what does your response
have to do with an OS controlling various forms of user memory access? OS
development context lost completely...
M> What I am trying to say is not that these things are right
M> or wrong, but that the implementation of the functions,
M> and thus the library, pre-supposes that the OS will work
M> in the Unix manner.

The error that you are making in your argument is that it is entirely
circular.

No, this has nothing to do with the conversation at hand. He was stating
that he didn't want POSIX or C libraries to influence the design of his OS.
He stated that using them in his OS would essentially force him to inherit
some of the concepts behind their design - most of which were due to UNIX,
such as a hierarchical filesystem and the functions or API used to access
the filesystem.
You are taking functions from the POSIX C language bindings
and arguing that they pre-suppose a Unix-like operating system. Of
course they do. POSIX is the _definition_ of a Unix-like operating
system.

No, UNIX is the _definition_ of a Unix-like operating system... POSIX is
the definition of a _portable_ Unix-like operating system.
However, you cannot make such an argument based upon
functions from the _Standard C Library_. The Standard C Library does
not either pre-suppose or mandate a Unix-like operating system.
Indeed, freestanding implementations of the C or C++ languages do not
pre-suppose operating systems at all.

He wasn't. You just restated his point from prior posts. But, he also
wants "advanced" features in his OS such as:
"file I/O, directory management, (non-automatic) memory management, system
clock, process execution, environment, and signals (C interrupts). This
functionality isn't part of the C language. It's part of the C library."
(quoting myself...)
M> my point is basically that the C library defines the API of the OS.
This
M> forces the OS to have that API, and this leaves very little leeway
for
M> the OS designer to deviate from another UNIX clone.

That point is wrong, as explained above. The Hurd and Plan 9 are
existence proofs of its incorrectness, as are the many embedded
systems written in the C and C++ languages.

First, I wasn't talking about embedded systems. I was talking about OSes
sufficiently advanced that applications can be written. "My assumption was
that if someone was writing an application for his OS, that his OS is
running on something powerful enough to have applications written for it,
say a PC or 1U router, and not on something far less powerful, say a Lego
Robot or a 1U digital effects processor. Anything less powerful than a PC
rarely runs more than a single master program." (quoting myself... Yes, I
know there are small devices which do. Please don't post examples.)

Second, I already brought up the issue of hiding the complexity of
implementing different OS concepts behind an existing API. "The question
is: 'Is the new paradigm sufficiently complex that it can't be easily hidden
behind the functions of the old paradigm?'" (quoting myself...) Matt has
yet to provide his thoughts here.


If you'd read the thread,...


Rod Pemberton
Rod,

Sorry for missing your question in your earlier post.

The idea of masking the new paradigm with an existing API works as long
as the two are functionally similar, but different in implementation.
This is similar to the object-oriented concept of keeping the class
definition the same but altering the implementation.

One place where the idea falls down is if the functionality is not to be
offered to the application programmer. For example, there is an OS in
development which has no file concept, from the application programmer's
point of view. - All data is treated as persistent, so you create an
object, and the OS does all the saving etc.

My argument for rethinking the old paradigm is that it dates from the
days of a single machine running a single program. Historically, this
lead to the idea of the BIOS functions, and then to the higher level
functions that form parts of the C library, the Unix library, et.al.
These came about to stop the application programmer having to know too
much about the hardware, and to re-invent the wheel for every
application. At this time there was no such thing as a virus, or the
internet, etc. By the time multi-tasking came along, these functions
were so ingrained into the concept of the API that a huge amount of work
was done to make the OS appear as though each application had sole use
of the machine. This was necessary so as not to break existing programs.
However, was this the right route?

Originally, there was the manager, ( the app) and the employee ( the
OS). This worked, but we now have one employee working for perhaps 50
managers. In a factory this would lead to huge inefficiencies, and such
is the case with an OS. On top of this, we now have to give the employee
the task of trying to work out which of the managers is allowed to ask
for what, and which are malicious. If we turn the paradigm on its head,
then it makes more sense. We should have one manager, and lots of
employees. This means that we have to put the kernel in control not just
of the hardware, but of the app. The app should carry out tasks on
behalf of the OS, not the other way around. This eliminates many of the
problems of resource conflicts, re-invention of the wheel, faulty code,
and viruses.

If the app is the emloyee, then they should never be allowed to tell the
manager to do something for them which affects the global system. Thus,
no library function should be provided which affects the global state of
the system. This includes file handling, device handling, or memory
handling.

Just my thoughts, for what they are worth.

Matt
 
J

J de Boyne Pollard

JdeBP> The error that you are making in your argument is that it is
JdeBP> entirely circular. You are taking functions from the POSIX
JdeBP> C language bindings and arguing that they pre-suppose a
JdeBP> Unix-like operating system. Of course they do. POSIX is
JdeBP> the _definition_ of a Unix-like operating system. However,
JdeBP> you cannot make such an argument based upon functions
JdeBP> from the _Standard C Library_. The Standard C Library
JdeBP> does not either pre-suppose or mandate a Unix-like
JdeBP> operating system. Indeed, freestanding implementations
JdeBP> of the C or C++ languages do not pre-suppose operating
JdeBP> systems at all.

M> It was exactly my point that C, (the language, with no
M> extensions) is OS independent, whilst the C library, (or the
M> POSIX extensions, or any of the other libraries which are
M> often added to, supplied with, or confused with the actual
M> language) presuppose an OS dependent interface.

And, as already explained once, that point is wrong. Once again: The
Standard C Library does not either pre-suppose or mandate a Unix-like
operating system. Freestanding implementations don't pre-suppose even
the existence of an operating system.

M> However, my argument is that many of the basic C library
M> functions ALSO pre-suppose an underlying structure which
M> is structured on existing OSes, and thus tends to force the
M> new OS writer to conform to the existing designs, rather
M> than branching off to something totally new.

As already explained once, there are plenty of existence proofs of the
contrary.

M> Looking through the C library, (not the POSIX one), and few
functions
M> spring to mind:

They shouldn't have. Taking just two of them: It's clearly false
that calloc() imposes anything at all related to the system API, let
alone impose a Unix-like operating system as you have been claiming.
And you need to read what the C Standard actually says about the
system() function. Here's a hint: It doesn't guarantee very much
functionality. It doesn't even guarantee the existence of a command
processor. The same error of thinking goes for signal(), raise(), and
most of the other functions that you listed. (Have a look at what the
C Standard actually guarantees about signals to programs. You can
start with paragraph 7.14.4.) I think that most of your error here is
based upon not knowing exactly what functionality of the Standard C
Library is actually specified in the first place by the C Standard,
what the constraints upon library implementors actually are. You
might _think_ that the system() function imposes the requirement that
a "/bin/sh" program exist capable of processing POSIX standard shell
commands. (After all, that's what the "man" page for that function
says. And it says that it "comforms to ANSI C".) But in actual fact,
the C Standard makes no such guarantee at all.

The people who worked on the C Standard expended a lot of effort to
ensure that Standard C was operating system agnostic. That the
Standard C Library can be and has been implemented on a wide range of
operating systems with widely varying paradigms, from AmigaDOS to Plan
9, as well as implemented for freestanding environments where there is
no operating system at all, is ample proof that your argument, that
the Standard C Library enforces a Unix-centric view (your own words),
is wrong.
 
J

J de Boyne Pollard

JdeBP> The Standard C Library does not either pre-suppose
JdeBP> or mandate a Unix-like operating system. Indeed,
JdeBP> freestanding implementations of the C or C++
JdeBP> languages do not pre-suppose operating systems at all.

RP> That was exactly Matt's point, if you had been reading the rest of
the
RP> a.o.d. thread... Your response seems to be without regard to the
context.

The irony here is that it is _you_ who has ignored the context.
Here's the context that you ignored: _Immediately below the text that
you have just quoted_ was Matt's actual point, in xyr very own words,
which is in contradiction to the above. Here it is for you again:

M> my point is basically that the C library defines the API of the
M> OS. This forces the OS to have that API, and this leaves
M> very little leeway for the OS designer to deviate from
M> another UNIX clone.

RP> He replied to your post, correcting you, [...]

No. He replied repeating the _very same mistake_ of conflating the
Standard C Library with the C language bindings to the POSIX system
API that I had already pointed out as being the error that he was
making; and making the additional mistake of thinking that Standard C
functions such as system() impose Unix-specific paradigms, in stark
contrast to what the C Standard _actually says_ about that function.
 
J

jacob navia

J said:
You
might _think_ that the system() function imposes the requirement that
a "/bin/sh" program exist capable of processing POSIX standard shell
commands. (After all, that's what the "man" page for that function
says. And it says that it "comforms to ANSI C".) But in actual fact,
the C Standard makes no such guarantee at all.

A conforming implementation of system() can be

int system(const char *p)
{
return 0;
}

Any usage of "system" provokes a warning:

"Warning: 'system' is NOT implemented\n"

The standard says about it:

If the argument is a null pointer, the system function returns nonzero
only if a command processor is available. If the argument is not a null
pointer, and the system function does return, it returns an
implementation-defined value.

The above implementation fulfills everything in the standard about
"system".
 
J

J de Boyne Pollard

M> The library functions which are included to allow process
M> launch, forking, and termination, imply that it is both
M> possible and desirable for a process to fork itself. This is
M> a fundamental part of the Unix thought process, but is
M> not essential for a working OS.

JdeBP> There are no Standard C Library functions for
JdeBP> process forking or overlaying. The fork() and execve()
JdeBP> functions are part of the C language bindings to
JdeBP> POSIX. They are not parts of the Standard C Library.

RP> We were discussing the use of these in OS development.
RP> Nowhere did Matt say they were part of the C library.

Rubbish. Here are xyr very words again:

M> What I am trying to say is not that these things are
M> right or wrong, but that the implementation of the
M> functions, and thus the library, pre-supposes that
M> the OS will work in the Unix manner.
M> [...]
M> my point is basically that the C library defines the API
M> of the OS. This forces the OS to have that API, and
M> this leaves very little leeway for the OS designer to
M> deviate from another UNIX clone.

M> Why should the user have access to memory mapping,
M> allocation and de-allocation routines? [...]

JdeBP> Similarly, mmap() is not a Standard C Library function.

M> It's true that mmap isn't part of the C library, but what does
M> your response have to do with an OS controlling various
M> forms of user memory access? OS development context
M> lost completely...

Again, it is not I but you who is losing the context. Here's what xe
went on to say immediately after that question:

M> What I am trying to say is not that these things are
M> right or wrong, but that the implementation of the
M> functions, and thus the library, pre-supposes that
M> the OS will work in the Unix manner.

Read the question, and that paragraph, and you'll get the context that
you are losing.

RP> He stated that using them in his OS would essentially
RP> force him to inherit some of the concepts behind their
RP> design - most of which were due to UNIX, such as a
RP> hierarchical filesystem and the functions or API used
RP> to access the filesystem.

And I've told you and xem three times now that that is wrong, not
least because the Standard C Library doesn't _have_ underlying
concepts such as the ones you mention.

JdeBP> However, you cannot make such an argument based
JdeBP> upon functions from the _Standard C Library_. The
JdeBP> Standard C Library does not either pre-suppose or
JdeBP> mandate a Unix-like operating system. Indeed, freestanding
JdeBP> implementations of the C or C++ languages do not
JdeBP> pre-suppose operating systems at all.

RP> He wasn't. You just restated his point from prior posts.

You are very confused. Xe was, and I've just _refuted_ xyr point.
Here's xyr point in xyr very own words _yet again_:

M> my point is basically that the C library defines the API
M> of the OS. This forces the OS to have that API, and
M> this leaves very little leeway for the OS designer to
M> deviate from another UNIX clone.

That point is wrong, as explained at length, and the aforementioned
refutes it.
 
K

Keith Thompson

jacob navia said:
A conforming implementation of system() can be

int system(const char *p)
{
return 0;
}

Any usage of "system" provokes a warning:

"Warning: 'system' is NOT implemented\n"

The standard says about it:

If the argument is a null pointer, the system function returns nonzero
only if a command processor is available. If the argument is not a null
pointer, and the system function does return, it returns an
implementation-defined value.

The above implementation fulfills everything in the standard about
"system".

Agreed. But as far as conformance is concerned, the warning (I assume
you mean a compile-time warning) is irrelevant. An implementation can
warn about anything it likes (and if system() with a non-null argument
doesn't do anything useful, then a compile-time warning would be a
good idea) -- but no such warning is required.
 
R

Rod Pemberton

I'm interested in discussion with Matt and a.o.d. about the OS issues, and
not in arguments with you about comprehension of or lack of context.

Also, something in your post seemed really odd to me. So, even you may find
it a bit rude, I'm going to ask anyway. What's with the "xe" for "he",
"xem" for "hem", "xyr" for "his"? You read or reread your posts prior to
reply, correct?
Here are xyr very words again:
Here's what xe
And I've told you and xem three times now
Xe was, and I've just _refuted_ xyr point.
Here's xyr point in xyr very own words _yet again_:

See, sometimes your using "xyr" for "him" and othertimes using "xyr" for
"your"... How am I supposed to determine that you've accurately ascribed my
text to me and not Matt's to me?

Just how did you manage type in "his" as "xyr"? That's really odd. Wrong
rows. Wrong fingers. Wrong sequence. It doesn't even seem to be Dvorak...

No, a custom keymap can't be it. Google has indexed a few posts like this
from you. Are you translating to French or Chinese and back again?

You seem to be using a custom newsreader which does non-standard indenting.
Has it become corrupted somehow?


Rod Pemberton
 
R

Rod Pemberton

J de Boyne Pollard said:
JdeBP> The Standard C Library does not either pre-suppose
JdeBP> or mandate a Unix-like operating system. Indeed,
JdeBP> freestanding implementations of the C or C++
JdeBP> languages do not pre-suppose operating systems at all.

RP> That was exactly Matt's point, if you had been reading the rest of
the
RP> a.o.d. thread... Your response seems to be without regard to the
context.

The irony here is that it is _you_ who has ignored the context.
Here's the context that you ignored: _Immediately below the text that
you have just quoted_ was Matt's actual point, in xyr very own words,
which is in contradiction to the above. Here it is for you again:

M> my point is basically that the C library defines the API of the
M> OS. This forces the OS to have that API, and this leaves
M> very little leeway for the OS designer to deviate from
M> another UNIX clone.

It was prior context earlier in the thread. He understands that C doesn't
require the library. That's exactly how he wrote his OS. This is basic
UNIX history:

0) a PDP-7 assembler was written.
1) the UNIX kernel was written in assembly for PDP-7 prior to the B & C
language interpreters and/or compilers.
2) B, a typeless language was written in assembly as a threaded interpreter
operating on a stack machine...like FORTH.
3) B was later rewritten to emit assembly, i.e., a simple compiler.
4) the UNIX kernel was ported to PDP-11 assembly.
5) the C compiler was developed from the B compiler.
6) the UNIX kernel was ported to C from assembly on the PDP-11. A prior
effort to port the kernel to C on the PDP-11 stalled.
7) no C library had been written.
8) a few C file I/O functions were written: read, write, open, creat,
close, link.
9) the I/O functions are based upon the PDP-7 UNIX filesystem which
Ritchie,Thompson,and Canaday had developed.
http://cm.bell-labs.com/cm/cs/who/dmr/chist.html
http://cm.bell-labs.com/cm/cs/who/dmr/hist.html

Trying to avoid "inheriting" the flavor of the PDP-7 filesystem through
functions in stdio.h, and/or unistd.h and fcntl.h is what Matt wants. I
already mentioned that it's really an issue of complexity of implementing
alternate filesystem behind the old functions.

The first is a good read. You'll find gems like:

"The rule, which survives in today's C, is that values of array type are
converted, when they appear in expressions, into pointers to the first of
the objects making up the array."

It brings up the question of whether arrays are really a type since a type
needs both a declaration and a form of usage within the language. Of
course, the array lacks the later. Here Ritchie ponders the incompleteness
of arrays and lack of solutions to make arrays a complete type:

"More fundamentally, the definition of C so specifically describes the
semantics of arrays that changes or extensions treating arrays as more
primitive objects, and permitting operations on them as wholes, become hard
to fit into the existing language."


Rod Pemberton
 
M

Maxim S. Shatskih

It brings up the question of whether arrays are really a type since a type
needs both a declaration and a form of usage within the language.

In C, arrays are treated as pointers only in _value_ context.

For instance, arrays are completely prohibited in lvalue context and are NOT
treated as pointers in sizeof() and structure field context.

"int a[]" is only equal to "int* a" if "a" will be used in value contexts only,
like, say, function formal parameter.

In a structure, "int a[]" is _by far not the same_ as "int* a"
 
A

Alexei A. Frounze

It brings up the question of whether arrays are really a type since a type
needs both a declaration and a form of usage within the language.

In C, arrays are treated as pointers only in _value_ context.

For instance, arrays are completely prohibited in lvalue context and are NOT
treated as pointers in sizeof() and structure field context.

"int a[]" is only equal to "int* a" if "a" will be used in value contexts only,
like, say, function formal parameter.

In a structure, "int a[]" is _by far not the same_ as "int* a"

There's another detail. If a is an array, then &a has a different type
from &a[0] and a but the same value.

Alex
 
M

Maxim S. Shatskih

There's another detail. If a is an array, then &a has a different type
from &a[0] and a but the same value.

Exactly.

"&a" is not a value context for "a".

Also note - "a", "&a" and "&a[0]" will all be the same _if placed in the value
context_.
 
K

Keith Thompson

Maxim S. Shatskih said:
In C, arrays are treated as pointers only in _value_ context.

It's not entirely clear what "value context" means. The actual rules
are simple enough that it's better to describe them exactly rather
than (or in addition to) summarizing them.
For instance, arrays are completely prohibited in lvalue context and are NOT
treated as pointers in sizeof() and structure field context.

"int a[]" is only equal to "int* a" if "a" will be used in value
contexts only, like, say, function formal parameter.

In a structure, "int a[]" is _by far not the same_ as "int* a"

Not quite.

The unary "&" operator requires an lvalue as its operand, and it
can be applied to an array.

The difference between "int a[]" and 'int *a" has nothing to do with
structures; the same rules apply (mostly) to structure members as to
standalone object declarations. These two declarations:

The actual rule (C99 6.3.2.1p3) is:

Except when it is the operand of the sizeof operator or the unary
& operator, or is a string literal used to initialize an array, an
expression that has type "array of _type_" is converted to an
expression with type "pointer to _type_" that points to the
initial element of the array object and is not an lvalue. If the
array object has register storage class, the behavior is
undefined.

See also section 6 of the comp.lang.c FAQ, <http://www.c-faq.com/>.
 
F

Flash Gordon

Maxim S. Shatskih wrote, On 30/09/07 19:35:
There's another detail. If a is an array, then &a has a different type
from &a[0] and a but the same value.

Exactly.

"&a" is not a value context for "a".

Since & is an operator it looks like a value context for a to me.
Also note - "a", "&a" and "&a[0]" will all be the same _if placed in the value
context_.

No.

int a[10];
int *b = a; /* valid */
int *c = &a; /* contraint violation requiring a diagnostic */
int *d = &a[0]; /* valid */
 
C

Chris Torek

Maxim S. Shatskih wrote, On 30/09/07 19:35:
There's another detail. If a is an array, then &a has a different type
from &a[0] and a but the same value.

Exactly.

"&a" is not a value context for "a".

(Elsethread, some point out that the C Standard does not use the
term "value context". I do use it myself, and may even be the
source of this particular meaning of it -- I contrast "value context"
with "object context" for various operators in C. There is one
even more special case which one might call "sizeof context",
but we can ignore that for now.)

Since & is an operator it looks like a value context for a to me.

It is not. Similarly, in:

x = y;

we name two variables and have one operator ("=", the ordinary
assignment operator) but we have two "contexts": x is in "object
context", because -- in this case -- we want to *change* its value,
and y is in "value context", because we want to find its value.

In this view (which is compatible with Standard C, but not actually
encoded in Standard C), array objects placed in "object context"
remain array objects, while array objects placed in "value context"
become pointers to the first element of the array.

One subtle point here is that this provides a specific model for
eventual extensions (in future version of C) that set entire array
objects. For instance:

int arr[10];
arr = expr;

is currently an error, but could become an assignment that sets
all ten elements of "arr". The value of the assignment would (in
my opinion anyway) be an "array rvalue" (a la func().arraymember
where func() returns a structure that contains a member of array
type), which is the one thing that this model does not address in
the first place. :)
Also note - "a", "&a" and "&a[0]" will all be the same _if placed
in the value context_.
No.

int a[10];
int *b = a; /* valid */
int *c = &a; /* contraint violation requiring a diagnostic */
int *d = &a[0]; /* valid */

Right. I think Maxim S. Shatskih meant "(with these things being
on the RHS of an assignment statement for instance) the values are
the same provided we disregard the types", but this is a bit like
saying that a person is a building, provided we disregard the
arrangements of the atoms in the molecules involved. If you take
away the type, you must -- at least in C -- also take away the
value. Values in C depend not only on the set of ones and zeros
in them, but also on the precise *interpretation* of those ones
and zeros. The interpretation is determined by type: take away
type and you have no idea whether the 32 bits sequence (0x40, 0x70,
0, 0) "means" 1081081856, 3.75, or something else entirely.
 

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

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top