C
Chris Dollin
Richard said:and more to
function_ptr();
which should, in theory, be written
*function_ptr();
(*function_ptr)();
Richard said:and more to
function_ptr();
which should, in theory, be written
*function_ptr();
No, but that is because - at least in theory, although in C it requires
a cast, and is one of the few contexts which IMO _should_ require one -
assigning an int to a pointer has a meaning. It's a non-portable,
implementation-defined meaning, but it _does_ have a meaning.
OTOH,
ptr.member = value;
has only one conceivable meaning. It can only reasonably mean the same
thing as
(*ptr).member = value;
alias
ptr->member = value;
Seen in this light,
ptr.member = value;
is less similar to
ptr = int_value;
and more to
function_ptr();
which should, in theory, be written
*function_ptr();
but for which we have also been given leave to eliminate the explicit
dereference, because there's no other way it can be interpreted anyway.
IMO, the same reasoning which gave us dereferenceless function pointer
calling - and that, /nota bene/, newly introduced by the first Standard,
because TTBOMK it was not allowed in K&R - could, and perhaps should,
give us dereferenceless struct and union pointer member taking.
A quick search of this group and its FAQ, and elsewhere, have not
answered this question to my satisfaction. Apologies if I missed
something obvious, either in the literature or my reasoning.
Can someone tell me why "->" exists? The compiler knows the difference
between a structure and a pointer to a structure, so why can't it just
let me write "foo.bar" in both cases and not have to go back and
rewrite things when I later decide I want a pointer instead of a value
or vice versa? I often change my mind about whether e.g. a function
should receive a pointer or the thing itself, and it's mildly
inconvenient to have to change all the code that references the
members.
Is there a historical reason? I read that dmr article on the history
of C, and he mentions a time when "foo->bar" would work regardless of
the type of "foo", with "bar" just describing an offset and the type
of the member value, but this confuses me -- was one not allowed to
use the same member name in two different structure types? But even if
the original reason was related to this, why was the division kept
after the type system got stronger?
[...]Keith Thompson said:(e-mail address removed) (Richard Bos) writes: [...]Seen in this light,
ptr.member = value;
is less similar to
ptr = int_value;
and more to
function_ptr();
which should, in theory, be written
*function_ptr();
but for which we have also been given leave to eliminate the explicit
dereference, because there's no other way it can be interpreted anyway.
Except that the reason 'function_ptr()' works is that the
function-call "operator" requires a function pointer as its first
operand. In a sense, 'function_name()' (calling a function using the
function's name directly) is the odd case, as it requires an implicit
conversion of the function's name to a pointer value. Without that
implicit conversion, you'd have to write '(&function_name)()'.
Now if I were designing the language from scratch, I might just drop
the implicit conversion of a function name to a function pointer and
make the function-call "operator" require an actual function. This
would require 'function_name()' for direct calls and
'(*function_ptr)()' for indirect calls. Of course this would break
existing code, so I wouldn't advocate making such a change now.
IMO, the same reasoning which gave us dereferenceless function pointer
calling - and that, /nota bene/, newly introduced by the first Standard,
because TTBOMK it was not allowed in K&R - could, and perhaps should,
give us dereferenceless struct and union pointer member taking.
I'll have to check my copy of K&R1.
user923005 said:It's one character less to get the member for:
foo->bar
than:
*(foo).bar
C programmers are incredibly lazy. It's like ls. It is one character
less than dir.
It's one character less to get the member for:
foo->bar
than:
*(foo).bar
Richard said:user923005 said:
Er, so what? They mean different things.
ITYM (*foo).bar
Keith Thompson said:Actually, in standard C 'ptr = some_value;' is a constraint violation,
so it doesn't have an unambiguous meaning. Some implementations do
allow it in some modes (for compatibility with pre-ANSI C), and as far
as I know all of them do an implicit conversion. But an
implementation could conceivably support 'ptr = some_value;' (where
some_value has the type of *ptr) as an extension with some different
semantics.
But allowing 'ptr = some_value;' to mean '*ptr = some_value;' would
cause other problems; it's already well-defined if ptr is of type
void** and some_value is of type void*.
Erm... isn't that what I said? It needs a cast, but when it gets it, it
has a meaning - but a system-specific meaning.
Keith Thompson said:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Keith Thompson said:(e-mail address removed) (Richard Bos) writes:
[...]
We don't write:
ptr = some_value;
No, but that is because - at least in theory, although in C it requires
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Erm... isn't that what I said? It needs a cast, but when it gets it, it
has a meaning - but a system-specific meaning.
Yes, I see that that's what you meant, but your statement that
"assigning an int to a pointer has a meaning" implies that assigning
*without a cast* has a meaning.
Keith Thompson said:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^(e-mail address removed) (Richard Bos) writes:
[...]
We don't write:
ptr = some_value;
No, but that is because - at least in theory, although in C it requires
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^a cast, and is one of the few contexts which IMO _should_ require one -
assigning an int to a pointer has a meaning. It's a non-portable,
implementation-defined meaning, but it _does_ have a meaning.
Actually, in standard C 'ptr = some_value;' is a constraint violation,
so it doesn't have an unambiguous meaning. Some implementations do
allow it in some modes (for compatibility with pre-ANSI C), and as far
as I know all of them do an implicit conversion. But an
implementation could conceivably support 'ptr = some_value;' (where
some_value has the type of *ptr) as an extension with some different
semantics.
Erm... isn't that what I said? It needs a cast, but when it gets it, it
has a meaning - but a system-specific meaning.
Yes, I see that that's what you meant, but your statement that
"assigning an int to a pointer has a meaning" implies that assigning
*without a cast* has a meaning.
Erm... *looks up* are you sure?
Richard
Keith Thompson said:Keith Thompson said:(e-mail address removed) (Richard Bos) writes:
(e-mail address removed) (Richard Bos) writes:
[...]
We don't write:
ptr = some_value;
No, but that is because - at least in theory, although in C it requires
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
a cast, and is one of the few contexts which IMO _should_ require one -
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
assigning an int to a pointer has a meaning. It's a non-portable,
implementation-defined meaning, but it _does_ have a meaning.
Actually, in standard C 'ptr = some_value;' is a constraint violation,
so it doesn't have an unambiguous meaning. Some implementations do
allow it in some modes (for compatibility with pre-ANSI C), and as far
as I know all of them do an implicit conversion. But an
implementation could conceivably support 'ptr = some_value;' (where
some_value has the type of *ptr) as an extension with some different
semantics.
Erm... isn't that what I said? It needs a cast, but when it gets it, it
has a meaning - but a system-specific meaning.
Yes, I see that that's what you meant, but your statement that
"assigning an int to a pointer has a meaning" implies that assigning
*without a cast* has a meaning.
Erm... *looks up* are you sure?
Yes, I'm sure.
Keith Thompson said:(e-mail address removed) (Richard Bos) writes:
(e-mail address removed) (Richard Bos) writes:
[...]
We don't write:
ptr = some_value;
No, but that is because - at least in theory, although in C
it requires
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
a cast, and is one of the few contexts which IMO _should_
require one -
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
assigning an int to a pointer has a meaning. It's a
non-portable, implementation-defined meaning, but it _does_
have a meaning.
Actually, in standard C 'ptr = some_value;' is a constraint
violation, so it doesn't have an unambiguous meaning. Some
implementations do allow it in some modes (for compatibility
with pre-ANSI C), and as far as I know all of them do an
implicit conversion. But an implementation could conceivably
support 'ptr = some_value;' (where some_value has the type of
*ptr) as an extension with some different semantics.
Erm... isn't that what I said? It needs a cast, but when it
gets it, it has a meaning - but a system-specific meaning.
Yes, I see that that's what you meant, but your statement that
"assigning an int to a pointer has a meaning" implies that
assigning *without a cast* has a meaning.
Erm... *looks up* are you sure?
Yes, I'm sure.
Then I humbly submit that you have not read the whole of my statement;
in particular, that you haven't read the side remark between hyphens,
which is an integral part of it.
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.