Address of an array = address of its 1st element: undecidable question?

Y

ymuntyan

I disagree. C99 3.17 is the standard's definition of the word "value":

    value
    precise meaning of the contents of an object when interpreted as
    having a specific type

This isn't a definition of the phrase "value of an object", it's a
definition of the word "value".  (And the flaw in that definition is
that it doesn't define the value of an expression.)

By this reasoning, the standard also defines the word "access",
is this correct? I think not, the standard defines what access
to an object means. Same thing with value, it does not define
what word "value" means, it defines what "value" means when applied
to a C object. I can't prove it, nor can you disprove it, but my
version makes most of the standard logical, so I'll stick to it.
Example: what does "sum of operands" mean? Math defines sum for
numbers, not for C entities. Is addition undefined in the C standard?

Yevgen
 
J

James Kuyper

Ben said:
....
| I'm not aware of any definition (or even description) of the C language
| that said that taking the address of an array was equivalent to taking
| the address of the first member of the array.

What does "equivalent to" mean? I don't know for sure, but since the
two operations produce different types it seems a stretch to say he is
at odds with any of the other writers. The current standard says that
when suitable converted they will compare equal, but I am sure he know
that!

Citation please?

There is wording to that effect in 6.7.2.1p13 with respect to structures
and their first member, but I couldn't find comparable wording about
arrays and their first element; by analogy with structures, I'd expect
such wording to be in section 6.7.5.2; I couldn't find it there, or
anywhere else that I looked.
Why does the Standard take care of the structure case and even
doesn't mention the array case ? I recall the Standard says :

-------------------- 8< -----------------------------
§6.7.2.1
A pointer to a structure object, suitably converted, points to its
initial member (...) and vice versa.
-------------------- >8 -----------------------------

How does one adapt this situation to the array case ? For instance,
declaring

int t[3];

can we expect (int *)&t will always equal to &t[0] ? and conservely, &t
will equal to (int (*)[3])&t[0] ?

Yes, I think so. See the definition of ==.

In order to apply that definition, you have to first prove where it is
that (int*)&t points. We all "know" that it points at the first int in
't'. But where does the standard say so? With only a few exceptions
(stucture*->member* and T*=>unsigned char*), the standard is remarkably
silent on the question of where it is that a pointer points, that is the
result from the conversion of a pointer of a different type. We all
"know" that, when the conversion is allowed, they point at the same
location in memory; but the standard fails to actually say so.
about them. If you were to permit me, I'd go on to say that they have
values that convert to equal void *s. The C standard is very clear
that a pointer to a whole object and pointer to one of its initial
sub-objects must compare equal (provided you convert the pointers so
that comparison is permitted) so the pointers have the same value in
that limited sense.
I suppose you are referring to the following excerpt of the Standard
:

-------------------- 8< -----------------------------
Two pointers compare equal if and only if both are null pointers, both
are pointers to the same object (including a pointer to an object and
a subobject at its beginning) or function, [...]
-------------------- >8 -----------------------------

Ah. I see you already have that in mind.

That doesn't quite cover it, because the standard fails to identify
which sub-object it is, if any, that (int*)&t points at.
 
Y

Yevgen Muntyan

James said:
Citation please?

There is wording to that effect in 6.7.2.1p13 with respect to structures
and their first member, but I couldn't find comparable wording about
arrays and their first element; by analogy with structures, I'd expect
such wording to be in section 6.7.5.2; I couldn't find it there, or
anywhere else that I looked.

>
>
> Citation please?
>
> There is wording to that effect in 6.7.2.1p13 with respect to structures
> and their first member, but I couldn't find comparable wording about
> arrays and their first element; by analogy with structures, I'd expect
> such wording to be in section 6.7.5.2; I couldn't find it there, or
> anywhere else that I looked.

It's not needed, because by definition of array its first byte
is the first byte of its first element. So, after *suitable*
conversion (e.g. to unsigned char*), the pointers will compare
equal, guaranteed (6.2.5p20, 6.3.2.3p7). Whether you can do

int a[3];
int *p = (int*)&a;
int ba = *p;

is another question (my guess is it's undefined, though
perhaps aliasing rules do allow this, but I don't care
anyway).

Structures are different because they may have holes and
so they need 1) explicit guarantee that there is no padding
at the beginning, and they need 2) explicit permission
for the pointer conversion because we want this conversion,
while nobody ever casts a pointer to an array to pointer
to its first element.

Yevgen
 
C

Chris Torek

[regarding &array vs &array[0] ...]

About the wording "the bit values are the same", did you notice that DMR
was suggesting that the bit value coincidence was not a portable
property, for being restricted to the "usual implementation" as he said
himself ? By the way, what exactly is the "usual implementation" ?

"Usual" would be those implementations we use every day on the x86,
ARM (cell phone), MIPS (Playstation), and other such CPUs. They
have a single linear ("flat") address space (sometimes "virtualized"
and/or "per process", so as to separate various running programs,
but each one gets to pretend it is running directly on the CPU with
all memory as a single flat space) where an address is always just
a byte-number. Byte-numbers start at some base -- not necessarily
zero -- and count up.
And what is exactly meant by "the bit values are the same" ? Does this
mean that my_array and &my_array yield the same bit representation ?

On "the usual implementation", yes.
If so, does the standard guarantee such a thing ?

No. Let us take a look at an unusual implementation.

First, consider some background from a couple of other languages.
In particular, consider the following bits of Lisp:

(defun hello-world ()
(print "hello world"))

(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))

This particular Lisp has "atoms", "lists", "strings", and "numbers"
(and probably splits numbers into integers, floating point numbers,
and bignums). 'defun, 'hello-world, 'factorial, 'n, and so on are
all "atoms". 1 is a number and "hello world" is a string. Putting
a series of atoms in parentheses forms a list, so (defun hello-world)
is a list of two atoms. To execute a list, we look up its first
atom (if it is an atom) to see how it is defined, and pass the rest
of the list to the code for that atom. Or, if we are asked to
execute a number or string, the result is just the number or string.

Lisp compilers, especially Lisp compilers for Lisp-machines, tend
to turn this into machine code in which different types -- i.e.,
atoms, lists, numbers, and strings -- have different "tag bits".
For instance, if there are exactly two tag bits available, we might
have tag = 00 for lists, 01 for atoms, 10 for numbers, and 11 for
strings. On conventional CPUs (Intel x86, MIPS, etc.), implementors
tend to use either the bottom or top couple of address bits for
these tags. That way, you can tell if an object in memory is a
list or an atom just by looking at a couple of its address bits --
and speed is important here because absolutely every operation in
the Lisp system starts by checking the tag bits first.

(Moreover, in a design hack, on CPUs that trap "bad" alignments,
we can put the tag bits at the bottom of the address, then make
*assumptions* about the low-order bits. For instance, if 00 is
for lists, we can *assume* that some pointer is for a list, follow
the pointer, and get an alignment-fault trap if the low two bits
are not zeros. Or, if we assume that some pointer is an "atom
pointer", we can use offset -1 on the address -- since per the
above, tag bits 01 mean "atom" -- and again we will get an alignment
fault trap if our assumption was wrong. So if our assumptions are
right, the code goes just as fast as if it were compiled C code,
and we get the speed of C, but -- unlike C -- complete type-safety.)

On machines specifically *designed* to run Lisp, the hardware
generally provides extra bits on each address that are purely there
for type-checking. So if we were to compile C code for this
hardware, we could make use of these extra bits.

Now let us consider a language like Pascal, in which arrays are
very different from pointers, and never interchangeable. In some
Pascal implementations, arrays are not simply "a block of memory",
and a two (or more) dimensional array is not *just* a bigger block
of memory in which A[j] is handled as if it were a[i * N + j]
(as compared with C, in which arrays normally *are* just big blocks
of memory, and "two-dimensional" arrays really are just handled
like this). We get runtime checking, in our compiled Pascal,
with the aid of an "array descriptor" and possibly even some
specialized CPU instruction (INDEX on the VAX, for instance).

The array descriptor is a sort of extensible structure and
looks something like this almost-C99 "struct":

struct array_descriptor {
void *base; /* address of array elements */
int dims; /* 1d, 2d, 3d? (hence 1 or more) */
size_t base_stride;
int bounds[dims][2]; /* size depends on dims */
};

The compiled code to handle A[j] looks something like this:

void *find_2d_array_element(struct array_descriptor *ap, int i, int j) {
void *result
size_t stride;

/* Require that the array really be 2d. */
if (ap->dims != 2) {
runtime_error("2d array access to %dd array", ap->dims);
/* NOTREACHED */
}

/* Verify that i and j are both within bounds. The lower
bound for each subscript is ap->dims[][0], and the upper
bound is ap->dims[][1]. */
if (i < ap->dims[0][0] || i > ap->dims[0][1])
runtime_error("array subscript 1 (%d) out of bounds [%d..%d]",
i, ap->dims[0][0], ap->dims[0][1]);
if (j < ap->dims[1][0] || i > ap->dims[1][1])
runtime_error("array subscript 2 (%d) out of bounds [%d..%d]",
j, ap->dims[0][0], ap->dims[0][1]);

/* Adjust index values i and j to work as if the array's
lower bounds were both 0, so that stride computation
is easier. Note that if the lower bounds ARE zero,
these have no effect. */
i -= ap->dims[0][0];
j -= ap->dims[1][0];

/* Use the base stride to find A[0][j] */
stride = ap->base_stride;
result = (unsigned char *)ap->base + j * stride;

/* Now find A[that] */
stride *= ap->dims[1][1] - ap->dims[1][0];
result = (unsigned char *)result + (stride * i);

return result;
}

(The result is used something like:

double *p = find_2d_array_element(descriptor, i, j);
use(*p);

for rvalues, and:

*p = PI;

for lvalues. Here I assume that "descriptor" is probably from an
array parameter, where the caller passed the address of the
descriptor. If the array were local, we might have &descriptor,
except if the array is local, we can optimize away most of this
code. We still need to compute the stride, but this is true in C
as well, and *that* machine code winds up being the same in C as
in any other language.)

(This sort of subscript checking before doing the stride computation
is why a lot of Pascal-like languages run a lot slower than a lot
of C-like languages. In many cases, the checks can be moved out
of loops or done entirely at compile-time, but *some* checks usually
remain, and they cost runtime. As we see over and over again,
people seem to prefer languages and systems that get the wrong
answer as fast as possible, by throwing away this kind of runtime
checking.)

Now, keeping both Lisp machines and typical Pascal implementations
in mind, consider how we might compile C code for a Lisp machine.
We have extra "tag bits" that go with every address. Depending on
how many tag bits we have, and how much runtime we are willing to
expend on runtime array subscript checking and so on, we could
choose to use the tag bits to carry information we then use to
locate array descriptors.[%] If we do all this, &array[0] and
&array might have *different* tag bits.

[% Major handwaving here ... :) The tag bits are invariably too
few to point directly to a separate descriptor, and too few even
to use as a table index into a table of descriptor-pointers. In
order to find the descriptor, we have to use a completely different
technique, in which we take the address of the "block of memory"
that holds the array elements, and look this up in an inversion
table. That is, we know that each descriptor D has a different
D.base, so we find the correct value of "i" by matching the
"memory block address" we have in hand against all possible D.base
values, using some sort of hash table. If we do this the obvious
way, we do not need any tag bits at all -- but we can use some of
the tag bits to speed up this search.]

Given two pointers with different tag bits, but the same "pointer
value" -- that is, one is a "Type A" pointer and the other is a
"Type B" pointer, but both point to the same "RAM address" -- do
we call these "the same value" or "different values"?

Clearly the "bit values" are different, if the term "bit values"
is taken to mean "ALL the bits, including the tag bits". But the
"address portion" of the values -- the result after stripping off
the tag bits -- is the same. So if we convert everything to
"void *", which strips off the original tag bits (pasting on tag
bits that say "void *" instead), the values will then be the same.
They were not the same originally, at least if by "values" we mean
"values including tag bits", but once we convert them to comparable
types, they *become* the same.

Since -- at least in C code -- we can only compare values after
converting them to some common type, the addresses will *appear*
to be the same.
How does one adapt this situation to the array case ? For instance,
declaring

int t[3];

can we expect (int *)&t will always equal to &t[0] ? and conservely, &t
will equal to (int (*)[3])&t[0] ?

I think it would not hurt the C standard to say so explicitly.
(On our Lisp-machine system above, it just means that after any
fiddling with the tag bits, the final bits that get compared in:

(int *)&t == &t[0]

are "the same", so that the result of the == operator is 1.) I
am not sure whether the C Standard actually says this now.

It *does* seem to say that:

(void *)&t == (void *)&t[0]

will always produce 1.
 
J

James Kuyper

It's not needed, because by definition of array its first byte
is the first byte of its first element. So, after *suitable*
conversion (e.g. to unsigned char*), the pointers will compare
equal, guaranteed (6.2.5p20, 6.3.2.3p7). Whether you can do

Given

T array[N];

Where T represents any particular object type, I agree that 6.3.2.3p7
guarantees that (char*)array == (char*)array[0]. I don't see that
there's anything with says that (T*)&array == &array[0], except when T
is a character type.
int a[3];
int *p = (int*)&a;
int ba = *p;

is another question (my guess is it's undefined, though
perhaps aliasing rules do allow this, but I don't care
anyway).

The standard fails to specify where p points; but I think it was clearly
the intent that p points at a[0]. If so, then assuming that 'a' gets
initialize before the evaluation of *p, ba should end up holding the
same value as a[0].
 
K

Keith Thompson

By this reasoning, the standard also defines the word "access",
is this correct? I think not, the standard defines what access
to an object means.

Here's the definition (C99 3.1):

access

(execution-time action) to read or modify the value of an object

I don't see a problem with that. I haven't done a complete search,
but I don't think the standard talks about "accessing" expressions as
opposed to objects. If it did, it would need to define what it means
to "access" an expression (as it fails to do for the "value" of an
expression).
Same thing with value, it does not define
what word "value" means, it defines what "value" means when applied
to a C object. I can't prove it, nor can you disprove it, but my
version makes most of the standard logical, so I'll stick to it.
Example: what does "sum of operands" mean? Math defines sum for
numbers, not for C entities. Is addition undefined in the C standard?

The C standard is an odd mix of formality and informality. In places,
technical terms are given specific definitions, but many of those
definitions are incomplete. In other places, plain informal English
is used rather than the more strictly defined technical terms, or
shortcuts are taken to avoid having to double or triple the size of
the text. In *most* such cases, a reasonably friendly reading works
(i.e., interpreting the text under the assumption that it's intended
to express something sensible, rather than an absolutely literal
interpretation). In this particular case, I think it's sufficiently
obvious what "sum of the operands" means, namely the sum of the
numeric values of the two expressions, interpreted as the appropriate
type.

Personally, I'd be happier if the standard were somewhat more formal
than it is; YMMV. At the very least, I'd like all the definitions to
be exhaustive and correct, so that a literal reading doesn't tell us
that 42 is an lvalue, or that it isn't an expression.
 
Y

Yevgen Muntyan

Keith said:
(e-mail address removed) writes:
[...]
But the question is whether the expressions 1 and 1u have the same
"value". Since the standard defines "value" in terms of "object",
No it doesn't, that's the thing. It defines value *of object*, it
doesn't define the human language term "value". I.e. it defines
what it means for a C object to have value 1, not what value 1
is.
I disagree. C99 3.17 is the standard's definition of the word "value":

value
precise meaning of the contents of an object when interpreted as
having a specific type

This isn't a definition of the phrase "value of an object", it's a
definition of the word "value". (And the flaw in that definition is
that it doesn't define the value of an expression.)
By this reasoning, the standard also defines the word "access",
is this correct? I think not, the standard defines what access
to an object means.

Here's the definition (C99 3.1):

access

(execution-time action) to read or modify the value of an object

I don't see a problem with that. I haven't done a complete search,
but I don't think the standard talks about "accessing" expressions

It does talk about accessing other things. Are expressions
special somehow? I only meant that the definition in bold
in that section doesn't mean that every use of the *word*
refers to that definition. So, if it defines the word
"access", how can you understand every use of this word?
There are uses where the definition doesn't make sense
(naturally). (Acrobat reader has this nifty feature by
the way, text search)
as
opposed to objects. If it did, it would need to define what it means
to "access" an expression (as it fails to do for the "value" of an
expression).

It doesn't fail to do that, it simply doesn't have to.
"Value" is a primary term. Value of an expression, number
1.2. *Value of object* *has* to be defined because an object
doesn't have a type, it doesn't make sense to talk about
a value of a region of storage. It's funny but true, if you
have a declaration

int a = 5;

then the value of the object designated by a isn't 5, there
is no value at all, unless you look at the type. On the other
hand, "5" has a type (int) and a value (5).
The C standard is an odd mix of formality and informality. In places,
technical terms are given specific definitions, but many of those
definitions are incomplete. In other places, plain informal English
is used rather than the more strictly defined technical terms, or
shortcuts are taken to avoid having to double or triple the size of
the text. In *most* such cases, a reasonably friendly reading works
(i.e., interpreting the text under the assumption that it's intended
to express something sensible, rather than an absolutely literal
interpretation). In this particular case, I think it's sufficiently
obvious what "sum of the operands" means, namely the sum of the
numeric values of the two expressions, interpreted as the appropriate
type.

So you choose to use obvious interpretation in this case, yet
you think that most of the occurrences of the word "value" in
the standard is wrong?

Oh well, just one more thing in the standard to argue about.
I do understand your point of view, I think, and I can't prove
that it's wrong. It's wrong of course, but I can't quote the
standard to prove that :)

Yevgen
 
B

Ben Bacarisse

James Kuyper said:
Citation please?

Already given (I am slow today) but I would add that there is another
conversion that I think meets my wording of "suitable". Given:

T array[N];

I think &array == (int (*)[])array is also guaranteed.
 
J

James Kuyper

Ben said:
Already given (I am slow today) ...

I haven't seen a relevant citation yet; I've explained why I felt that
Yevgen's citation wasn't relevant. Do you have response to my objections?


....
but I would add that there is another
conversion that I think meets my wording of "suitable". Given:

T array[N];

I think &array == (int (*)[])array is also guaranteed.

Only if T is a typedef for 'int'.
 
B

Ben Bacarisse

James Kuyper said:
I haven't seen a relevant citation yet; I've explained why I felt that
Yevgen's citation wasn't relevant.

We must have crossed wires. My citation is 6.3.2.3p7 requiring the
pointers to compare equal when "suitably converted" (to a pointer to a
character type). I thought you'd agreed with that elsewhere.
Do you have response to my objections?

Do you mean that (T *)&array might not point to the first sub-object
of a T array? No, I don't. I would have an objection to an
implementation that did something that odd, but I think it is
permitted.

The easiest way for "C on the DS9000" to do this is to make
(T *)&array badly aligned for a T object. That is permitted and just
constructing the pointer is UB (same citation). I don't think there
is any need for it to make (T *)&array point to some element other
than the first.
...
but I would add that there is another
conversion that I think meets my wording of "suitable". Given:

T array[N];
I think &array == (int (*)[])array is also guaranteed.

Only if T is a typedef for 'int'.

Rats! But I presume you got the idea: that there was another
"suitable" conversion not yet given in the thread. Of course I
intended to type: "&array == (T (*)[])array".
 
J

James Kuyper

Ben said:
We must have crossed wires. My citation is 6.3.2.3p7 requiring the
pointers to compare equal when "suitably converted" (to a pointer to a
character type). I thought you'd agreed with that elsewhere.

I thought you were referring to converting one pointer to the other
pointer's type. That is how I interpret the only case where the standard
actually uses the phrase "suitably converted" (6.7.2.1p13). If you are
talking about converting both pointers into character type pointers,
then I agree that it is covered by 6.3.2.3p7.
Do you mean that (T *)&array might not point to the first sub-object
of a T array? No, I don't. I would have an objection to an
implementation that did something that odd, but I think it is
permitted.

The easiest way for "C on the DS9000" to do this is to make
(T *)&array badly aligned for a T object. ...

I don't think it was the intent of the committee to allow for it to be
misaligned. I think that, if that is allowed, it is a result of an error
in the wording of the standard, not something that was deliberately
allowed for.
... That is permitted and just
constructing the pointer is UB (same citation). I don't think there
is any need for it to make (T *)&array point to some element other
than the first.

There is no reason I can think of why any implementation should do
anything with a permitted pointer conversion other than producing a
pointer of the new type that points at the same location in memory as
the original pointer. I doubt that there are any implementations that do
anything different from that. I think there's a huge amount of code
based upon the assumption that this is the way pointer conversions work.
It bothers me that the standard falls short of actually guaranteeing
that this is the way pointer conversions work.
 
C

candide

Chris said:
[regarding &array vs &array[0] ...]

Thanks for having copiously answered my question.

One question more please :
> (...) I
> am not sure whether the C Standard actually says this now.
>
> It *does* seem to say that:
>
> (void *)&t == (void *)&t[0]
>
> will always produce 1.


I would like to emphasise your answer in this way :

"It does *seem* to say that:"

So, if i understand well, the Standard doesn't make certain the above
equality yields 1 ?
 
C

candide

Ben said:
(...) I am not really sure anymore
what your point is. Do you disagree that, suitable converted, a
pointer to an array and a pointer to the first element of an array
will compare equal?

This is exactly my point (and BTW, what do you mean by "suitably
converted" ?).
If so, I think you are wrong. If you think
someone has said they won't, then who?

Nobody said so. But some refrained from answering the question.
 
C

Chris Torek

Chris said:
[The C Standard] *does* seem to say that:
(void *)&t == (void *)&t[0]
will always produce 1.

I would like to emphasise your answer in this way :

"It does *seem* to say that:"

So, if i understand well, the Standard doesn't make certain the above
equality yields 1 ?

I think that it *does* say that. The wording is not as clear as
I would like, though. If others disagree with me (about the result
of the comparison above always being 1), I would like to see their
reasoning, and perhaps a DR is called for.
 
Y

Yevgen Muntyan

Chris said:
Chris said:
[The C Standard] *does* seem to say that:
(void *)&t == (void *)&t[0]
will always produce 1.

I would like to emphasise your answer in this way :

"It does *seem* to say that:"

So, if i understand well, the Standard doesn't make certain the above
equality yields 1 ?

I think that it *does* say that.

6.5.9p6 says that:

"Two pointers compare equal if and only if both are null pointers,
both are pointers to the same object (including a pointer to an object
and a subobject at its beginning)..."

Yevgen
 
C

candide

Yevgen Muntyan wrote :
6.5.9p6 says that:

"Two pointers compare equal if and only if both are null pointers,
both are pointers to the same object (including a pointer to an object
and a subobject at its beginning)..."

As I pointed out in an earlier post, this wording is proper to C99.
[sorry but I'm only interested in C89 Standard.]
 
B

Ben Bacarisse

candide said:
This is exactly my point (and BTW, what do you mean by "suitably
converted" ?).

Well that is clear then. By "suitably converted" I just meant
converted so that the statement is true. In other words it was a way
of saying that there is are conversions that make it true without
having to say what. It was deliberately vague because exactly what is
guaranteed buy the standard and what is simply a reasonable
interpretation of it is not 100% clear. Given

T array[N];

I am sure that (char *)&array == (char *)array is guaranteed by
section 6.3.2.3 paragraph 7.

I think only the most deliberately contrived interpretation of the
standard would not extend the guarantee to both (void *)&array ==
(void *)array and to &array == (T (*)[])array. I consider all of the
above suitable for the purposes of my quote.

I think the intent is that (T *)&array == array but there are enough
gaps in the wording that it can't be guaranteed to the satisfaction of
all.
Nobody said so. But some refrained from answering the question.

Well, no one is obliged to answer anything. I hope it is all clear
now! It is of very little practical value since there is an obvious
and guaranteed way to get a pointer to any element of an array.
 
B

Ben Bacarisse

candide said:
Yevgen Muntyan wrote :
6.5.9p6 says that:

"Two pointers compare equal if and only if both are null pointers,
both are pointers to the same object (including a pointer to an object
and a subobject at its beginning)..."

As I pointed out in an earlier post, this wording is proper to C99.
[sorry but I'm only interested in C89 Standard.]

Ah, then you may have a problem. As far as I know there is no way to
correct or clarify an obsolete standard. You just need to live with
the uncertainty. I take it your interest is purely theoretical? I
can't see any practical consequences of the loose wording in C89 and I
would be prepared to bet that no conforming C89 implementation will
have (void *)&array != (void *)array if, for some odd reason you need
to reply on that property.
 
J

James Kuyper

Chris said:
Chris said:
[The C Standard] *does* seem to say that:
(void *)&t == (void *)&t[0]
will always produce 1.

I would like to emphasise your answer in this way :

"It does *seem* to say that:"

So, if i understand well, the Standard doesn't make certain the above
equality yields 1 ?

I think that it *does* say that. The wording is not as clear as
I would like, though. If others disagree with me (about the result
of the comparison above always being 1), I would like to see their
reasoning, and perhaps a DR is called for.

When you convert a pointer from a pointer type to void*, where does the
resulting pointer point? I know where I and everyone else expects it to
point; I know where it will point under essentially every implementation
of C. I don't know where the standard actually says so. There is such a
statement for char*, but not for void*.
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top