Discussion:
Null terminated strings: bad or good?
(too old to reply)
CBFalconer
2009-01-07 21:41:07 UTC
Permalink
[...]
I claim that calloc didn't really succeed. It just converted the
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object. The type returned by sizeof is size_t (which must
be capable of holding that result). SIZE_MAX is the maximum value
of a size_t value. These facts suffice to prove that no object can
exceed SIZE_MAX in size.

I have cross-posted to comp.std.c for further resolution, if any.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
jameskuyper
2009-01-07 21:52:50 UTC
Permalink
Post by CBFalconer
[...]
I claim that calloc didn't really succeed. It just converted the
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object.
No, it only returns the size of the object whose name is the right
operand of sizeof. When you have an object, but no way to name it for
use as the operand of sizeof, then the requirement on sizeof cannot
constrain the size of that object.
Keith Thompson
2009-01-07 22:07:21 UTC
Permalink
Post by CBFalconer
[...]
I claim that calloc didn't really succeed. It just converted the
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object. The type returned by sizeof is size_t (which must
be capable of holding that result). SIZE_MAX is the maximum value
of a size_t value. These facts suffice to prove that no object can
exceed SIZE_MAX in size.
I have cross-posted to comp.std.c for further resolution, if any.
One more time. The argument to sizeof is either a parenthesized type
name or an expression. sizeof does not, in general, compute the size
of an object. In particular, an object created by calloc cannot be
named by an expression, and therefore cannot be an operand of sizeof.

You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-07 23:57:41 UTC
Permalink
Post by Keith Thompson
Post by CBFalconer
[...]
I claim that calloc didn't really succeed. It just converted the
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object. The type returned by sizeof is size_t (which must
be capable of holding that result). SIZE_MAX is the maximum value
of a size_t value. These facts suffice to prove that no object can
exceed SIZE_MAX in size.
I have cross-posted to comp.std.c for further resolution, if any.
One more time. The argument to sizeof is either a parenthesized type
name or an expression. sizeof does not, in general, compute the size
of an object. In particular, an object created by calloc cannot be
named by an expression, and therefore cannot be an operand of sizeof.
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.

6.5.3.4 The sizeof operator

... snip ...

Semantics

[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
jameskuyper
2009-01-08 00:07:17 UTC
Permalink
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
[...]
I claim that calloc didn't really succeed. It just converted the
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object. The type returned by sizeof is size_t (which must
be capable of holding that result). SIZE_MAX is the maximum value
of a size_t value. These facts suffice to prove that no object can
exceed SIZE_MAX in size.
I have cross-posted to comp.std.c for further resolution, if any.
One more time. The argument to sizeof is either a parenthesized type
name or an expression. sizeof does not, in general, compute the size
of an object. In particular, an object created by calloc cannot be
named by an expression, and therefore cannot be an operand of sizeof.
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
It covers all "what"? To make your argument valid, it would have to be
"all objects", but what this covers is "all sizeof expressions". To
prove relevance of this citation to your argument, you have to
identify a sizeof expression applied to the object allocated by the
call to calloc().
Post by CBFalconer
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
Keith Thompson
2009-01-08 00:09:24 UTC
Permalink
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
[...]
I claim that calloc didn't really succeed. It just converted the
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object. The type returned by sizeof is size_t (which must
be capable of holding that result). SIZE_MAX is the maximum value
of a size_t value. These facts suffice to prove that no object can
exceed SIZE_MAX in size.
I have cross-posted to comp.std.c for further resolution, if any.
One more time. The argument to sizeof is either a parenthesized type
name or an expression. sizeof does not, in general, compute the size
of an object. In particular, an object created by calloc cannot be
named by an expression, and therefore cannot be an operand of sizeof.
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
Nope.

The standard *does not say* that the sizeof operator can be used to
determine the size of any object. It can determine the size of a type
or of an expression. In particular, it cannot be used (directly) to
determine the size of an anonymous object, such as one created by a
call to calloc(). So the description of the sizeof operator is
irrelevant to the question.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Richard
2009-01-08 00:23:36 UTC
Permalink
Post by Keith Thompson
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
[...]
I claim that calloc didn't really succeed. It just converted the
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object. The type returned by sizeof is size_t (which must
be capable of holding that result). SIZE_MAX is the maximum value
of a size_t value. These facts suffice to prove that no object can
exceed SIZE_MAX in size.
I have cross-posted to comp.std.c for further resolution, if any.
One more time. The argument to sizeof is either a parenthesized type
name or an expression. sizeof does not, in general, compute the size
of an object. In particular, an object created by calloc cannot be
named by an expression, and therefore cannot be an operand of sizeof.
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
Nope.
The standard *does not say* that the sizeof operator can be used to
determine the size of any object. It can determine the size of a type
or of an expression. In particular, it cannot be used (directly) to
determine the size of an anonymous object, such as one created by a
call to calloc(). So the description of the sizeof operator is
irrelevant to the question.
I would like to make a point and then ask a serious question here:

*IF* Chuck were called Bill Cunningham you would probably have stopped
responding to him by now.

How on earth can you encourage him being so wrong so often by replying
to him? *IF* Falconer were a polite and well meaning poster who was here
to improve his knowledge in addition to aiding and abetting new C
adopters then all well and good. But he isn't. I mean, hell, we ALL make
mistakes. However, he is here to bully, provoke and generally piss
people off with his arrogant and, at times, nonsensical ramblings and
obvious lack of real practical C in the real world.
--
I'm not a person who particularly had heros when growing up.
- Dennis Ritchie when asked about the hero worship coming from c.l.c
Kenny McCormack
2009-01-08 00:57:45 UTC
Permalink
In article <gk3h2c$s0j$***@rgrdev.motzarella.org>,
Richard <***@gmail.com> wrote:
...
Post by Richard
adopters then all well and good. But he isn't. I mean, hell, we ALL make
mistakes. However, he is here to bully, provoke and generally piss
people off with his arrogant and, at times, nonsensical ramblings and
obvious lack of real practical C in the real world.
You have a problem with that?
CBFalconer
2009-01-08 22:15:58 UTC
Permalink
Keith Thompson wrote:
... snip ...
Post by Keith Thompson
The standard *does not say* that the sizeof operator can be used
to determine the size of any object. It can determine the size
of a type or of an expression. In particular, it cannot be used
(directly) to determine the size of an anonymous object, such as
one created by a call to calloc(). So the description of the
sizeof operator is irrelevant to the question.
Firstly, an object can be an expression. Simply name it.
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.

int i, *p;
...
i ... is an expression, consisting of the name i alone.
It has the value of whatever i has been set to.

p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Wojtek Lerch
2009-01-08 22:24:33 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
The standard *does not say* that the sizeof operator can be used
to determine the size of any object. It can determine the size
of a type or of an expression. In particular, it cannot be used
(directly) to determine the size of an anonymous object, such as
one created by a call to calloc(). So the description of the
sizeof operator is irrelevant to the question.
Firstly, an object can be an expression. Simply name it.
No, an object is an area of memory in the abstract machine. An expression
is a sequence of tokens in the source code of a program.
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
Maybe; or maybe it only references a portion of it. That depends on the
size of the object that calloc created and the size of the type that ptr is
declared to point to. Those two sizes are not neccessarily the same.
Keith Thompson
2009-01-08 22:37:30 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
The standard *does not say* that the sizeof operator can be used
to determine the size of any object. It can determine the size
of a type or of an expression. In particular, it cannot be used
(directly) to determine the size of an anonymous object, such as
one created by a call to calloc(). So the description of the
sizeof operator is irrelevant to the question.
Firstly, an object can be an expression. Simply name it.
The object in question was created by a call to calloc(). It has no
name. And no, an object cannot be an expression; an expression can
designate to an object.
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
int i, *p;
...
i ... is an expression, consisting of the name i alone.
It has the value of whatever i has been set to.
p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
What expression refers to the object -- the entire object -- created
by calloc (assuming it returns a non-null pointer)? *p certainly
doesn't.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-09 01:28:41 UTC
Permalink
Post by Keith Thompson
Post by CBFalconer
... snip ...
Post by Keith Thompson
The standard *does not say* that the sizeof operator can be used
to determine the size of any object. It can determine the size
of a type or of an expression. In particular, it cannot be used
(directly) to determine the size of an anonymous object, such as
one created by a call to calloc(). So the description of the
sizeof operator is irrelevant to the question.
Firstly, an object can be an expression. Simply name it.
The object in question was created by a call to calloc(). It has
no name. And no, an object cannot be an expression; an expression
can designate to an object.
How can you say that? int i; declares an object, named i. i in
executable code references it, and depending on position it may
read or write that object. If a read, the expression value is (so
far) the value of i.
Post by Keith Thompson
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
int i, *p;
...
i ... is an expression, consisting of the name i alone.
It has the value of whatever i has been set to.
p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
What expression refers to the object -- the entire object --
created by calloc (assuming it returns a non-null pointer)?
*p certainly doesn't.
*p certainly does. calloc, if successful, returned a pointer to a
memory block. That was put in p. *p dereferences it, and accesses
the object. If the size requested in calloc exceeds SIZE_MAX
calloc should retun a NULL, and fail. The object is one or more
items of the type of *p (allowing for arrays).
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Richard Tobin
2009-01-09 01:47:37 UTC
Permalink
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
int i, *p;
...
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
What expression refers to the object -- the entire object --
created by calloc (assuming it returns a non-null pointer)?
*p certainly doesn't.
*p certainly does. calloc, if successful, returned a pointer to a
memory block. That was put in p. *p dereferences it, and accesses
the object.
No, it accesses the single int at the start of it. And sizeof(*p)
is sizeof(int), not SIZE_MAX*2.

-- Richard
--
Please remember to mention me / in tapes you leave behind.
CBFalconer
2009-01-09 02:27:12 UTC
Permalink
Post by Richard Tobin
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
int i, *p;
...
p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
What expression refers to the object -- the entire object --
created by calloc (assuming it returns a non-null pointer)?
*p certainly doesn't.
*p certainly does. calloc, if successful, returned a pointer to a
memory block. That was put in p. *p dereferences it, and accesses
the object.
No, it accesses the single int at the start of it. And sizeof(*p)
is sizeof(int), not SIZE_MAX*2.
You have a point there. But calloc still has not created anything
with the allegedly specified size, because of unsigned arithmetic,
for one thing.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
James Kuyper
2009-01-09 04:10:50 UTC
Permalink
CBFalconer wrote:
...
Post by CBFalconer
You have a point there. But calloc still has not created anything
with the allegedly specified size, because of unsigned arithmetic,
for one thing.
I think you're mistakenly referring to the fact that SIZE_MAX*2 is
required to have a value of SIZE_MAX-1 (assuming that SIZE_MAX >
INT_MAX, which is not required, but usually true).
However, calloc(nmemb,size) is not defined as allocating an amount of
memory of size equal to nmemb*size. It's defined as allocating enough
memory to hold an array (a single object!) containing nmemb objects of
the specified size.

calloc(SIZE_MAX,2) is permitted to return NULL, but no conforming
implementation can have calloc() return a pointer to memory with
insufficient space to store SIZE_MAX objects, each of 2 bytes in size,
and that requires a lot more than SIZE_MAX*2 bytes of memory, if you
interpret SIZE_MAX*2 as being evaluated according to the rules of C,
rather than the rules of mathematics.
Tim Rentsch
2009-01-09 09:13:54 UTC
Permalink
Post by James Kuyper
...
Post by CBFalconer
You have a point there. But calloc still has not created anything
with the allegedly specified size, because of unsigned arithmetic,
for one thing.
I think you're mistakenly referring to the fact that SIZE_MAX*2 is
required to have a value of SIZE_MAX-1 (assuming that SIZE_MAX >
INT_MAX, which is not required, but usually true).
However, calloc(nmemb,size) is not defined as allocating an amount of
memory of size equal to nmemb*size. It's defined as allocating enough
memory to hold an array (a single object!) containing nmemb objects of
the specified size.
calloc(SIZE_MAX,2) is permitted to return NULL, but no conforming
implementation can have calloc() return a pointer to memory with
insufficient space to store SIZE_MAX objects, each of 2 bytes in size,
and that requires a lot more than SIZE_MAX*2 bytes of memory, if you
interpret SIZE_MAX*2 as being evaluated according to the rules of C,
rather than the rules of mathematics.
You lost me on the part after the last 'if'. How does an evaluation
of SIZE_MAX*2 ever yield a value that is a lot more than SIZE_MAX*2,
assuming (under the reasonably standard assumptions) that the evaluation
is done using an unsigned type at least as big as unsigned int?
Or are you saying something else entirely?
James Kuyper
2009-01-09 11:43:37 UTC
Permalink
...
Post by Tim Rentsch
Post by James Kuyper
I think you're mistakenly referring to the fact that SIZE_MAX*2 is
required to have a value of SIZE_MAX-1 (assuming that SIZE_MAX >
INT_MAX, which is not required, but usually true).
However, calloc(nmemb,size) is not defined as allocating an amount of
memory of size equal to nmemb*size. It's defined as allocating enough
memory to hold an array (a single object!) containing nmemb objects of
the specified size.
calloc(SIZE_MAX,2) is permitted to return NULL, but no conforming
implementation can have calloc() return a pointer to memory with
insufficient space to store SIZE_MAX objects, each of 2 bytes in size,
and that requires a lot more than SIZE_MAX*2 bytes of memory, if you
interpret SIZE_MAX*2 as being evaluated according to the rules of C,
rather than the rules of mathematics.
You lost me on the part after the last 'if'. How does an evaluation
of SIZE_MAX*2 ever yield a value that is a lot more than SIZE_MAX*2,
assuming (under the reasonably standard assumptions) that the evaluation
is done using an unsigned type at least as big as unsigned int?
Or are you saying something else entirely?
I'm saying something quite different. When I refer to the mathematical
value of an expression, I most definitely do NOT mean "using an unsigned
type at least as big as unsigned int". I would have thought that the
meaning of the mathematical value was obvious. However, if a definition
in C terms is needed, then it could be described as the value that would
result if every operand were converted before evaluation of the
expression to a complex floating point type with infinite precision, and
no upper or lower limits on the range of finite values of the real and
imaginary components of that number that can be represented. No such
type could exist in a real implementation of C, but that doesn't prevent
us from talking about what the result would be of evaluating an
expression using such a type.

In a great many particular cases it's feasible to represent the
mathematical value of an expression exactly using a C type that is real
rather than complex, integral rather than floating point, or unsigned
rather than signed. However, it's fundamentally an abstract concept
independent of machine representations, and in the general case it will
either be too big or too small or require too much precision for any
real-world C data type to represent it exactly; the best that can be
done is to round it to the nearest representable value (which might be
+/- infinity). None of those problems apply in this case, however.

Assume, for simplicity, that SIZE_MAX has it's minimum allowed value of
65535. Then mathematically, SIZE_MAX*2 has a value of 131070, while
according to the rules of C (assuming that SIZE_MAX > INT_MAX),
SIZE_MAX*2 would have a value of 65534, a much smaller number.
Richard
2009-01-09 02:29:25 UTC
Permalink
Post by Richard Tobin
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
int i, *p;
...
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
What expression refers to the object -- the entire object --
created by calloc (assuming it returns a non-null pointer)?
*p certainly doesn't.
*p certainly does. calloc, if successful, returned a pointer to a
memory block. That was put in p. *p dereferences it, and accesses
the object.
No, it accesses the single int at the start of it. And sizeof(*p)
is sizeof(int), not SIZE_MAX*2.
-- Richard
This is getting silly. Is this some kind of "in" joke?
--
I'm not a person who particularly had heros when growing up.
- Dennis Ritchie when asked about the hero worship coming from c.l.c
Keith Thompson
2009-01-09 01:53:41 UTC
Permalink
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
... snip ...
Post by Keith Thompson
The standard *does not say* that the sizeof operator can be used
to determine the size of any object. It can determine the size
of a type or of an expression. In particular, it cannot be used
(directly) to determine the size of an anonymous object, such as
one created by a call to calloc(). So the description of the
sizeof operator is irrelevant to the question.
Firstly, an object can be an expression. Simply name it.
The object in question was created by a call to calloc(). It has
no name. And no, an object cannot be an expression; an expression
can designate to an object.
How can you say that? int i; declares an object, named i. i in
executable code references it, and depending on position it may
read or write that object. If a read, the expression value is (so
far) the value of i.
An expression can *designate* an object.

An expression cannot *be* an object.

The name of an object and the object itself are two different things.

An expression exists in the source of a C translation unit. An object
exists during the execution of a C program.
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
int i, *p;
...
i ... is an expression, consisting of the name i alone.
It has the value of whatever i has been set to.
p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
What expression refers to the object -- the entire object --
created by calloc (assuming it returns a non-null pointer)?
*p certainly doesn't.
*p certainly does.
It certainly does not. It refers to a subset of the object. I asked
for an expression that refers to the entire object.
Post by CBFalconer
calloc, if successful, returned a pointer to a
memory block. That was put in p. *p dereferences it, and accesses
the object. If the size requested in calloc exceeds SIZE_MAX
calloc should retun a NULL, and fail.
Why should it? You keep making this claim. One more time, if calloc
successfully allocates an object of size SIZE_MAX*2, what clause of
the standard does the implementation it violate? (SIZE_MAX*2 is meant
to be a mathematical expression, not affected by C unsigned type
wraparound semantics.)
Post by CBFalconer
The object is one or more
items of the type of *p (allowing for arrays).
*p is not that object.

Ok, let's consider another case, setting aside the huge allocation
issue for the moment:

int count = <some number>;
int *p = calloc(count, sizeof(int));

If calloc succeeds, it allocates an object whose size is
count*sizeof(int). What expression refers to that object? Note that
*p refers to an object whose size is sizeof(int); that's not the
object I'm talking about.

To put it another way:

sizeof <BLANK> == count*sizeof(int)

Fill in the blank in a manner that makes this expression true and is
directly relevant to the object allocated by calloc() in the code
above.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-09 02:34:07 UTC
Permalink
Keith Thompson wrote:
... snip ...
Post by Keith Thompson
sizeof <BLANK> == count*sizeof(int)
Fill in the blank in a manner that makes this expression true and
is directly relevant to the object allocated by calloc() in the
code above.
You haven't shown the reduction to range 0..SIZE_MAX, performed by
the unsigned arithmetic. All those operands are type size_t.

(sizeof <BLANK>) % (SIZE_MAX+1) ==
(count % (SIZE_MAX+1)) * (sizeof(int) % (SIZE_MAX+1))

and it may need another % (SIZE_MAX+1).
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Keith Thompson
2009-01-09 02:58:26 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
sizeof <BLANK> == count*sizeof(int)
Fill in the blank in a manner that makes this expression true and
is directly relevant to the object allocated by calloc() in the
code above.
You haven't shown the reduction to range 0..SIZE_MAX, performed by
the unsigned arithmetic. All those operands are type size_t.
(sizeof <BLANK>) % (SIZE_MAX+1) ==
(count % (SIZE_MAX+1)) * (sizeof(int) % (SIZE_MAX+1))
and it may need another % (SIZE_MAX+1).
I didn't show it because it isn't relevant to the example. Assume
that all values are reasonably small, so that the multiplication
doesn't wrap around. Assume that sizeof(int) is no larger than 8, and
count is no larger than 100.

Repeating what I posted upthread:

Ok, let's consider another case, setting aside the huge allocation
issue for the moment:

int count = <some number>;
int *p = calloc(count, sizeof(int));

If calloc succeeds, it allocates an object whose size is
count*sizeof(int). What expression refers to that object? Note that
*p refers to an object whose size is sizeof(int); that's not the
object I'm talking about.

To put it another way:

sizeof <BLANK> == count*sizeof(int)

Fill in the blank in a manner that makes this expression true and is
directly relevant to the object allocated by calloc() in the code
above.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-09 23:24:16 UTC
Permalink
Keith Thompson wrote:
... snip ...
Post by Keith Thompson
Ok, let's consider another case, setting aside the huge allocation
int count = <some number>;
int *p = calloc(count, sizeof(int));
If calloc succeeds, it allocates an object whose size is
count*sizeof(int). What expression refers to that object? Note
that *p refers to an object whose size is sizeof(int); that's not
the object I'm talking about.
sizeof <BLANK> == count*sizeof(int)
Fill in the blank in a manner that makes this expression true and
is directly relevant to the object allocated by calloc() in the
code above.
In this case things are no different than calling malloc with that
product as argument, except that the memory is not initialized. I
don't think there is any argument that that size is unavailable
with standard C methods. Replace BLANK by "((count) * sizeof
(int))", bearing in mind the unsigned calculation.

I greatly doubt that you will find ANY calloc that does other than
compute the product and call malloc. That means that the system
may report success, but has actually allocated much less than the
desired memory. To me, that is a glaring calloc fault.

To justify that, consider that it is not portably possible to
allocate more than one memory segment with malloc, and guarantee
that the segments are combinable.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Keith Thompson
2009-01-10 00:14:15 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
Ok, let's consider another case, setting aside the huge allocation
int count = <some number>;
int *p = calloc(count, sizeof(int));
If calloc succeeds, it allocates an object whose size is
count*sizeof(int). What expression refers to that object? Note
that *p refers to an object whose size is sizeof(int); that's not
the object I'm talking about.
sizeof <BLANK> == count*sizeof(int)
Fill in the blank in a manner that makes this expression true and
is directly relevant to the object allocated by calloc() in the
code above.
In this case things are no different than calling malloc with that
product as argument, except that the memory is not initialized. I
don't think there is any argument that that size is unavailable
with standard C methods. Replace BLANK by "((count) * sizeof
(int))", bearing in mind the unsigned calculation.
So you claim that

sizeof ((count) * sizeof (int)) == count*sizeof(int)

is true? I don't think that's what you meant -- and I don't think
you're taking this seriously.

<BLANK> should be replaced with an expression that designates the
object (the *entire* object) allocated by the calloc() call.
Post by CBFalconer
I greatly doubt that you will find ANY calloc that does other than
compute the product and call malloc. That means that the system
may report success, but has actually allocated much less than the
desired memory. To me, that is a glaring calloc fault.
A calloc implementation that blindly multiplies its two arguments,
ignoring any wraparound, is buggy. I think I've seen such
implementations, but three systems I've just tried don't have this
problem. On all three systems, this program:

#include <stdio.h>
#include <stdlib.h>

#define MY_SIZE_MAX ((size_t)-1)
/* SIZE_MAX isn't always available */

int main(void)
{
void *c = calloc(MY_SIZE_MAX, MY_SIZE_MAX);
void *m = malloc(MY_SIZE_MAX * MY_SIZE_MAX);
printf("calloc %s\n", c == NULL ? "failed" : "succeeded");
printf("malloc %s\n", m == NULL ? "failed" : "succeeded");
return 0;
}

produces this output:

calloc failed
malloc succeeded
Post by CBFalconer
To justify that, consider that it is not portably possible to
allocate more than one memory segment with malloc, and guarantee
that the segments are combinable.
I fail to see the relevance. What is a "memory segment", and why
would I want to combine more than one of them?

No implementation is *required* to support allocating objects larger
than SIZE_MAX bytes using calloc(). The argument is whether an
implementation is *allowed* to do so.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
James Kuyper
2009-01-09 04:13:52 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
sizeof <BLANK> == count*sizeof(int)
Fill in the blank in a manner that makes this expression true and
is directly relevant to the object allocated by calloc() in the
code above.
You haven't shown the reduction to range 0..SIZE_MAX, performed by
the unsigned arithmetic. All those operands are type size_t.
Such reduction is irrelevant to calculation of the size needed by a call
to calloc(). The memory needed is defined in terms of a count of
objects, and the size of the objects, not in terms of the result of
multiplying those two numbers.
jameskuyper
2009-01-09 00:03:06 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
The standard *does not say* that the sizeof operator can be used
to determine the size of any object. It can determine the size
of a type or of an expression. In particular, it cannot be used
(directly) to determine the size of an anonymous object, such as
one created by a call to calloc(). So the description of the
sizeof operator is irrelevant to the question.
Firstly, an object can be an expression. Simply name it.
How do you name an object allocated by calloc? You can name a pointer
to it, but not the object itself. This isn't C++, where you could
assign *ptr to a reference variable.
Post by CBFalconer
Secondly, the object created by calloc is referencable. Simply
store the returned value in a pointer variable. Then *ptr
references it.
Is an implementation allowed to declare a type that is too large for
sizeof(type) to return the correct value? You have two options. Given

typedef char toobig[SIZE_MAX][2];
toobig *ptr = calloc(SIZE_MAX, 2);
size_t type_size = sizeof(toobig);
size_t object_size = sizeof *ptr;

Note: the value of object_size is completely independent of the value
of 'ptr'. The sizeof expression is still perfectly valid even if ptr
is a null pointer. It would still be valid even if ptr were
uninitialized and contained a trap representation.

1) If toobig can be defined despite the fact that type_size cannot
possibly contain the correct value, why is calloc() constrained to
return a null pointer just because object_size cannot possibly contain
the correct value?

2) If toobig cannot be defined because it is too big, how can you
possibly declare a pointer type such that *ptr=calloc(SIZE_MAX,2) has
a size too big for object_size to contain the correct value?

No matter which of the two ways you resolve that decision, the
behavior of calloc() is unconstrained by the requirements placed on
sizeof.
Post by CBFalconer
int i, *p;
...
i ... is an expression, consisting of the name i alone.
It has the value of whatever i has been set to.
p = calloc(SIZE_MAX, 2);
if (p) puts("calloc is bad");
Your snippet STILL fails to show any use of sizeof in a fashion that
imposes limits on the behavior of calloc().
CBFalconer
2009-01-09 01:31:42 UTC
Permalink
... snip ...
Post by jameskuyper
Post by CBFalconer
Firstly, an object can be an expression. Simply name it.
How do you name an object allocated by calloc? You can name a
pointer to it, but not the object itself. This isn't C++, where
you could assign *ptr to a reference variable.
You name it by prefixing the name of the pointer with a *.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
James Kuyper
2009-01-09 04:24:00 UTC
Permalink
Post by CBFalconer
... snip ...
Post by jameskuyper
Post by CBFalconer
Firstly, an object can be an expression. Simply name it.
How do you name an object allocated by calloc? You can name a
pointer to it, but not the object itself. This isn't C++, where
you could assign *ptr to a reference variable.
You name it by prefixing the name of the pointer with a *.
That's not the name of the object, it's an lvalue expression that refers
to an object. However, that would be still be sufficient for my purposes
if it was in fact the entire object allocated by the call to calloc().
It is not. It is only an object of type char[2]. The entire object has
the type char[SIZE_MAX][2].

Most importantly, sizeof(*ptr) presents absolutely no problems; it's
value is 2, far smaller than the minimum value for SIZE_MAX, which is
65535 (7.18.3p2).

I order to use an argument based upon sizeof's requirements, to
constrain the behavior of calloc(), you have to apply sizeof to
something for which the value would be greater than SIZE_MAX, unless
calloc() returns NULL. So far, you have yet to identify that something.

For that matter, you've also failed to identify a problem that having
calloc() return NULL would solve. sizeof(*ptr) has the exact same value,
whether or not calloc() returned NULL.
Tim Rentsch
2009-01-09 09:06:23 UTC
Permalink
Post by James Kuyper
Post by CBFalconer
... snip ...
Post by jameskuyper
Post by CBFalconer
Firstly, an object can be an expression. Simply name it.
How do you name an object allocated by calloc? You can name a
pointer to it, but not the object itself. This isn't C++, where
you could assign *ptr to a reference variable.
You name it by prefixing the name of the pointer with a *.
That's not the name of the object, it's an lvalue expression that refers
to an object. However, that would be still be sufficient for my purposes
if it was in fact the entire object allocated by the call to calloc().
It is not. It is only an object of type char[2]. The entire object has
the type char[SIZE_MAX][2].
Most importantly, sizeof(*ptr) presents absolutely no problems; it's
value is 2, far smaller than the minimum value for SIZE_MAX, which is
65535 (7.18.3p2).
I think a little too much context was snipped. The earlier posting
Post by James Kuyper
Post by CBFalconer
Is an implementation allowed to declare a type that is too large for
sizeof(type) to return the correct value? You have two options. Given
typedef char toobig[SIZE_MAX][2];
toobig *ptr = calloc(SIZE_MAX, 2);
size_t type_size = sizeof(toobig);
size_t object_size = sizeof *ptr;
With these definitions, it is sizeof (*ptr)[0] that is has the
value 2, or equivalently sizeof **ptr. The expression sizeof(*ptr)
references a type whose size is indeed mathematically > SIZE_MAX.
James Kuyper
2009-01-09 11:48:51 UTC
Permalink
Post by Tim Rentsch
Post by James Kuyper
Post by CBFalconer
... snip ...
Post by jameskuyper
Post by CBFalconer
Firstly, an object can be an expression. Simply name it.
How do you name an object allocated by calloc? You can name a
pointer to it, but not the object itself. This isn't C++, where
you could assign *ptr to a reference variable.
You name it by prefixing the name of the pointer with a *.
That's not the name of the object, it's an lvalue expression that refers
to an object. ...
... However, that would be still be sufficient for my purposes
if it was in fact the entire object allocated by the call to calloc().
It is not. It is only an object of type char[2]. The entire object has
the type char[SIZE_MAX][2].
Most importantly, sizeof(*ptr) presents absolutely no problems; it's
value is 2, far smaller than the minimum value for SIZE_MAX, which is
65535 (7.18.3p2).
to here. It was a big, stupid mistake.
Post by Tim Rentsch
I think a little too much context was snipped. The earlier posting
Post by James Kuyper
Post by CBFalconer
Is an implementation allowed to declare a type that is too large for
sizeof(type) to return the correct value? You have two options. Given
typedef char toobig[SIZE_MAX][2];
toobig *ptr = calloc(SIZE_MAX, 2);
size_t type_size = sizeof(toobig);
size_t object_size = sizeof *ptr;
With these definitions, it is sizeof (*ptr)[0] that is has the
value 2, or equivalently sizeof **ptr. The expression sizeof(*ptr)
references a type whose size is indeed mathematically > SIZE_MAX.
My apologies, I forgot that it was my own example that we were
discussing, rather than his previous example. Aaaargh! In my defense, I
was very tired at the end of a very long day.
CBFalconer
2009-01-09 23:27:43 UTC
Permalink
James Kuyper wrote:
... snip ...
Post by James Kuyper
For that matter, you've also failed to identify a problem that
having calloc() return NULL would solve. sizeof(*ptr) has the
exact same value, whether or not calloc() returned NULL.
i.e. ptr = calloc(<SPECS>);
sz = sizeof(*ptr);

I haven't checked, but if ptr is NULL I believe that is an error.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Ben Pfaff
2009-01-10 00:02:31 UTC
Permalink
Post by CBFalconer
i.e. ptr = calloc(<SPECS>);
sz = sizeof(*ptr);
I haven't checked, but if ptr is NULL I believe that is an error.
No, the operand of sizeof is not evaluated, except in one special
case:

The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
Keith Thompson
2009-01-10 00:17:23 UTC
Permalink
Post by CBFalconer
... snip ...
Post by James Kuyper
For that matter, you've also failed to identify a problem that
having calloc() return NULL would solve. sizeof(*ptr) has the
exact same value, whether or not calloc() returned NULL.
i.e. ptr = calloc(<SPECS>);
sz = sizeof(*ptr);
I haven't checked, but if ptr is NULL I believe that is an error.
Why haven't you checked? And what kind of "error" do you think it is?

In sizeof(*ptr), the expression *ptr is not evaluated, so the result
is not affected by whether calloc() succeeded.

You've quoted 6.5.3.4p2 several times here.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Wojtek Lerch
2009-01-08 00:11:37 UTC
Permalink
Post by CBFalconer
Post by Keith Thompson
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
You'd think that; but what about sizeof(char[SIZE_MAX][2])?

Anyway, since no exceptions are mentioned, apparently the intent was to
cover all possible operands. But the operand of sizeof is not an object;
the operand is an expression or a type. Even if the standard means to
forbid types larger than SIZE_MAX bytes and expressions that have such
types, that doesn't necessarily mean that objects larger than SIZE_MAX bytes
are forbidden too.
Post by CBFalconer
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
Hallvard B Furuseth
2009-01-08 15:02:10 UTC
Permalink
Post by Wojtek Lerch
Post by CBFalconer
Post by Keith Thompson
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
You'd think that; but what about sizeof(char[SIZE_MAX][2])?
What about it? Since sizeof shall return the size in bytes, that array
type is an error. At least gcc and sun CC think so, and it makes sense
to me.
Post by Wojtek Lerch
Post by CBFalconer
6.5.3.4 The sizeof operator
... snip ...
[#2] The sizeof operator yields the size (in bytes) of its operand,
(...) If the type of the operand is a variable length array type,
the operand is evaluated; (...)
int foo(size_t x) { long a[x]; return sizeof(a); }

Now the value of foo(SIZE_MAX) is wrong - if such a large auto
array doesn't produce a run-time exception, anyway.
--
Hallvard
Wojtek Lerch
2009-01-08 15:31:26 UTC
Permalink
Post by Hallvard B Furuseth
Post by Wojtek Lerch
Post by CBFalconer
Post by Keith Thompson
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
You'd think that; but what about sizeof(char[SIZE_MAX][2])?
What about it? Since sizeof shall return the size in bytes, that array
type is an error. At least gcc and sun CC think so, and it makes sense
to me.
What do you mean by "error"? A constraint violation? That would imply that
there's a constraint somewhere in the standard that is violated -- do you
happen to know the exact chapter and verse?

And is it an "error" to use that type in any context, or just as an operand
of sizeof?
Post by Hallvard B Furuseth
Post by Wojtek Lerch
Post by CBFalconer
6.5.3.4 The sizeof operator
... snip ...
[#2] The sizeof operator yields the size (in bytes) of its operand,
(...) If the type of the operand is a variable length array type,
the operand is evaluated; (...)
int foo(size_t x) { long a[x]; return sizeof(a); }
If you add "typedef" in front of "long a[x]", the implementation won't have
Post by Hallvard B Furuseth
Now the value of foo(SIZE_MAX) is wrong - if such a large auto
array doesn't produce a run-time exception, anyway.
As far as I can tell, the standard doesn't explicitly forbid naming types
larger than SIZE_MAX bytes, or even applying sizeof to such types -- it just
describes the semantics of sizeof in a way that is logically impossible for
such types.
Hallvard B Furuseth
2009-01-08 16:13:47 UTC
Permalink
Post by Wojtek Lerch
Post by Hallvard B Furuseth
Post by Wojtek Lerch
You'd think that; but what about sizeof(char[SIZE_MAX][2])?
What about it? Since sizeof shall return the size in bytes, that array
type is an error. At least gcc and sun CC think so, and it makes sense
to me.
What do you mean by "error"? A constraint violation? That would imply
that there's a constraint somewhere in the standard that is violated --
do you happen to know the exact chapter and verse?
Whoops, good point. I've been too long away from C standardese.
Post by Wojtek Lerch
And is it an "error" to use that type in any context, or just as an
operand of sizeof?
Those compilers reject 'typedef long foo[SIZE_MAX];'.

[Rearranging the reply a bit]
Post by Wojtek Lerch
As far as I can tell, the standard doesn't explicitly forbid naming
types larger than SIZE_MAX bytes, or even applying sizeof to such types
-- it just describes the semantics of sizeof in a way that is logically
impossible for such types.
Yup.

For fixed-size types, two natural fixes would be to make either the type
or the sizeof() a constraint violation. I think rejecting the type
Post by Wojtek Lerch
Post by Hallvard B Furuseth
Post by Wojtek Lerch
Post by CBFalconer
6.5.3.4 The sizeof operator
... snip ...
[#2] The sizeof operator yields the size (in bytes) of its operand,
(...) If the type of the operand is a variable length array type,
the operand is evaluated; (...)
int foo(size_t x) { long a[x]; return sizeof(a); }
If you add "typedef" in front of "long a[x]", the implementation won't
Right again.
Post by Wojtek Lerch
Post by Hallvard B Furuseth
Now the value of foo(SIZE_MAX) is wrong - if such a large auto
array doesn't produce a run-time exception, anyway.
--
Hallvard
CBFalconer
2009-01-08 22:21:00 UTC
Permalink
Wojtek Lerch wrote:
... snip ...
Post by Wojtek Lerch
As far as I can tell, the standard doesn't explicitly forbid
naming types larger than SIZE_MAX bytes, or even applying sizeof
to such types -- it just describes the semantics of sizeof in a
way that is logically impossible for such types.
Thank you. Precisely. Append the words 'to exist'.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Wojtek Lerch
2009-01-08 22:43:31 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Wojtek Lerch
As far as I can tell, the standard doesn't explicitly forbid
naming types larger than SIZE_MAX bytes, or even applying sizeof
to such types -- it just describes the semantics of sizeof in a
way that is logically impossible for such types.
Thank you. Precisely. Append the words 'to exist'.
I was going to say "to implement for such types".

The words of the standard specify semantics of sizeof in a way that is a
logical impossibility when the size of the operand is greater than SIZE_MAX.
Conceivably, there are many possible ways to remove the illogicall
requirement from the standard:

#1 Say that the behaviour is undefined when the operand of sizeof is larger
than SIZE_MAX bytes
#2 Say that the result is unspecified (or maybe implementation-defined) when
the operand of sizeof is larger than SIZE_MAX bytes
#3 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes
#4 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes, along with any other uses of such types
#5 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes, along with any other uses of sizeof
#6 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes, along with any other uses of expressions

I don't see any reason to pick #4 over #1, #2, or #3. Personally, I find #4
unnecessarily restrictive and almost as arbitrary as #5 or #6.
CBFalconer
2009-01-09 01:38:48 UTC
Permalink
Post by Wojtek Lerch
Post by CBFalconer
... snip ...
Post by Wojtek Lerch
As far as I can tell, the standard doesn't explicitly forbid
naming types larger than SIZE_MAX bytes, or even applying sizeof
to such types -- it just describes the semantics of sizeof in a
way that is logically impossible for such types.
Thank you. Precisely. Append the words 'to exist'.
I was going to say "to implement for such types".
The words of the standard specify semantics of sizeof in a way
that is a logical impossibility when the size of the operand is
greater than SIZE_MAX. Conceivably, there are many possible ways
This argument only arises because of the prototype of calloc.
Nowhere else is there any possibility of creating oversized objects
(considering the definition of size_t and SIZE_MAX). calloc is
quite capable of protecting itself by checking that the size
requested does not exceed SIZE_MAX. It has the ability to signal
this (or other failures) by returning NULL.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
James Kuyper
2009-01-09 04:30:00 UTC
Permalink
...
Post by CBFalconer
Post by Wojtek Lerch
The words of the standard specify semantics of sizeof in a way
that is a logical impossibility when the size of the operand is
greater than SIZE_MAX. Conceivably, there are many possible ways
This argument only arises because of the prototype of calloc.
Nowhere else is there any possibility of creating oversized objects
(considering the definition of size_t and SIZE_MAX).
No, the problem is quite independent of calloc(), as has been repeatedly
pointed out. It is equally impossible for sizeof to return the specified
value when applied to types that are too big.

Nor is it possible to apply sizeof to the object allocated by a call to
calloc() in such a way as to display this problem, without first
declaring a type for which sizeof(type) would be equally problematic.
CBFalconer
2009-01-09 23:32:08 UTC
Permalink
... snip ...
Post by James Kuyper
Post by CBFalconer
This argument only arises because of the prototype of calloc.
Nowhere else is there any possibility of creating oversized
objects (considering the definition of size_t and SIZE_MAX).
No, the problem is quite independent of calloc(), as has been
repeatedly pointed out. It is equally impossible for sizeof to
return the specified value when applied to types that are too big.
There are no "types that are too big". Their sizes have been
calculated using unsigned arithmetic, which cannot return a value
larger than SIZE_MAX. That result is in the symbol tables for
compilation.

If the compilation is on a cross-compiler, the authors should have
handled the appropriate size limits.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Richard Tobin
2009-01-10 00:18:31 UTC
Permalink
Post by CBFalconer
There are no "types that are too big". Their sizes have been
calculated using unsigned arithmetic
Do you have any evidence for that? I don't recall anything that
implies that the size of objects is calculated using C arithmetic
(rather than everyday arithmetic) at all.

-- Richard
--
Please remember to mention me / in tapes you leave behind.
Wojtek Lerch
2009-01-09 05:07:26 UTC
Permalink
Post by CBFalconer
Post by Wojtek Lerch
The words of the standard specify semantics of sizeof in a way
that is a logical impossibility when the size of the operand is
greater than SIZE_MAX. Conceivably, there are many possible ways
This argument only arises because of the prototype of calloc.
No, I was talking about specifying types larger than SIZE_MAX bytes.
The
argument about calloc is a separate issue.
Post by CBFalconer
Nowhere else is there any possibility of creating oversized objects
(considering the definition of size_t and SIZE_MAX).
It's the other way around: the standard never forbids declaring
objects or
types larger than SIZE_MAX. The definition of size_t and SIZE_MAX
implies a
limit on the types for which sizeof can possibly return its specified
value,
but it says nothing about types that aren't operands of the sizeof
operator.
Post by CBFalconer
calloc is
quite capable of protecting itself by checking that the size
requested does not exceed SIZE_MAX. It has the ability to signal
this (or other failures) by returning NULL.
Sure, but the question is whether it's *required* to do so. And
that's not
the question that I was originally arguing about.
Tim Rentsch
2009-01-09 08:43:51 UTC
Permalink
Post by Wojtek Lerch
Post by CBFalconer
... snip ...
Post by Wojtek Lerch
As far as I can tell, the standard doesn't explicitly forbid
naming types larger than SIZE_MAX bytes, or even applying sizeof
to such types -- it just describes the semantics of sizeof in a
way that is logically impossible for such types.
Thank you. Precisely. Append the words 'to exist'.
I was going to say "to implement for such types".
The words of the standard specify semantics of sizeof in a way that is a
logical impossibility when the size of the operand is greater than SIZE_MAX.
Conceivably, there are many possible ways to remove the illogicall
#1 Say that the behaviour is undefined when the operand of sizeof is larger
than SIZE_MAX bytes
#2 Say that the result is unspecified (or maybe implementation-defined) when
the operand of sizeof is larger than SIZE_MAX bytes
#3 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes
#4 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes, along with any other uses of such types
#5 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes, along with any other uses of sizeof
#6 Forbid expressions where the operand of sizeof is larger than SIZE_MAX
bytes, along with any other uses of expressions
I don't see any reason to pick #4 over #1, #2, or #3. Personally, I find #4
unnecessarily restrictive and almost as arbitrary as #5 or #6.
What the Standard does is #2; the result of sizeof is always
implementation-defined, including cases where the mathematical
size is greater than SIZE_MAX.


P.S. My apologies if this posting appears twice; my news poster
gave an unexpected error message.
Richard
2009-01-08 23:57:21 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Wojtek Lerch
As far as I can tell, the standard doesn't explicitly forbid
naming types larger than SIZE_MAX bytes, or even applying sizeof
to such types -- it just describes the semantics of sizeof in a
way that is logically impossible for such types.
Thank you. Precisely. Append the words 'to exist'.
Chuck is the only man I ever came across who can be wrong and make the
person correcting him look foolish to those not familiar with his rather
slimy blame proportioning.
--
I'm not a person who particularly had heros when growing up.
- Dennis Ritchie when asked about the hero worship coming from c.l.c
Wojtek Lerch
2009-01-09 00:08:24 UTC
Permalink
Post by Richard
Chuck is the only man I ever came across who can be wrong and make the
person correcting him look foolish to those not familiar with his rather
slimy blame proportioning.
He made me look foolish? Damn! Couldn't you have kept that to yourself?
;-)
Tim Rentsch
2009-01-09 08:13:13 UTC
Permalink
Post by Wojtek Lerch
Post by Hallvard B Furuseth
Post by Wojtek Lerch
Post by CBFalconer
Post by Keith Thompson
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
You'd think that; but what about sizeof(char[SIZE_MAX][2])?
What about it? Since sizeof shall return the size in bytes, that array
type is an error. At least gcc and sun CC think so, and it makes sense
to me.
What do you mean by "error"? A constraint violation? That would imply that
there's a constraint somewhere in the standard that is violated -- do you
happen to know the exact chapter and verse?
And is it an "error" to use that type in any context, or just as an operand
of sizeof?
Post by Hallvard B Furuseth
Post by Wojtek Lerch
Post by CBFalconer
6.5.3.4 The sizeof operator
... snip ...
[#2] The sizeof operator yields the size (in bytes) of its operand,
(...) If the type of the operand is a variable length array type,
the operand is evaluated; (...)
int foo(size_t x) { long a[x]; return sizeof(a); }
If you add "typedef" in front of "long a[x]", the implementation won't have
Post by Hallvard B Furuseth
Now the value of foo(SIZE_MAX) is wrong - if such a large auto
array doesn't produce a run-time exception, anyway.
As far as I can tell, the standard doesn't explicitly forbid naming types
larger than SIZE_MAX bytes, or even applying sizeof to such types -- it just
describes the semantics of sizeof in a way that is logically impossible for
such types.
It isn't logically impossible, because implementations are required
to meet the specifications only for programs that are strictly
conforming, which doesn't include any program that does a
sizeof(long[SIZE_MAX]) (when sizeof(long) > 1); for types
whose size is mathematically greater than SIZE_MAX, sizeof
can take advantage of its result being implementation-defined
and yield any size_t value whatsoever.
James Kuyper
2009-01-09 12:21:14 UTC
Permalink
...
Post by Tim Rentsch
Post by Wojtek Lerch
Post by Hallvard B Furuseth
Post by CBFalconer
6.5.3.4 The sizeof operator
... snip ...
[#2] The sizeof operator yields the size (in bytes) of its operand,
(...) If the type of the operand is a variable length array type,
the operand is evaluated; (...)
int foo(size_t x) { long a[x]; return sizeof(a); }
If you add "typedef" in front of "long a[x]", the implementation won't have
Post by Hallvard B Furuseth
Now the value of foo(SIZE_MAX) is wrong - if such a large auto
array doesn't produce a run-time exception, anyway.
As far as I can tell, the standard doesn't explicitly forbid naming types
larger than SIZE_MAX bytes, or even applying sizeof to such types -- it just
describes the semantics of sizeof in a way that is logically impossible for
such types.
It isn't logically impossible, because implementations are required
to meet the specifications only for programs that are strictly
conforming, which doesn't include any program that does a
sizeof(long[SIZE_MAX]) (when sizeof(long) > 1);
Please identify the way in which such a program fails to be strictly
conforming. The value of such an expression is implementation-defined,
but that would prevent the program from being strictly conforming only
if the program produces output that depends upon that value, and it's
easy to avoid having that happen. The behavior is not undefined; 6.5.3.4
defines precisely what the value of that expression should be.
Unfortunately, it also specifies the type of that expression, and the
value cannot be expressed in that type, so it's impossible for that
expression to actually have that value; but that's precisely what you've
denied is relevant.
Post by Tim Rentsch
... for types
whose size is mathematically greater than SIZE_MAX, sizeof
can take advantage of its result being implementation-defined
and yield any size_t value whatsoever.
No, it cannot. The standard first defines that sizeof "yields the size
(in bytes) of it's operand", and then later says "the value of the
result is implementation-defined". What this means, in effect, is that
it's actually the size of its operand that is implementation-defined;
the fact that the value is implementation-defined does not give the
implementation the option of having sizeof yield any value other than
"the size (in bytes) of it's operand".

The standard contains many statements that constrain an implementation's
freedom to define that size. sizeof(long) must be an integer greater
than 1. The size of an array must be exactly the amount of space
required to store contiguously a number of objects of the element type
of the array that is equal to the specified length of the array.

Therefore, an implementation is not free to give long[SIZE_MAX] any size
other than the mathematical value of SIZE_MAX*sizeof(long), even though
it's impossible for sizeof to yield that value if sizeof(long)>1.
Francis Glassborow
2009-01-09 14:24:57 UTC
Permalink
Post by James Kuyper
The standard contains many statements that constrain an implementation's
freedom to define that size. sizeof(long) must be an integer greater
than 1.
No, it must be greater than 0 (there is nothing in the standard that
requires that long requires more storage than char)
--
Note that robinton.demon.co.uk addresses are no longer valid.
jameskuyper
2009-01-09 17:20:10 UTC
Permalink
Post by Francis Glassborow
Post by James Kuyper
The standard contains many statements that constrain an implementation's
freedom to define that size. sizeof(long) must be an integer greater
than 1.
No, it must be greater than 0 (there is nothing in the standard that
requires that long requires more storage than char)
Sorry - that was a type created by a bad edit. The original said
"greater than or equal to 1".
Wojtek Lerch
2009-01-09 15:26:18 UTC
Permalink
Post by Tim Rentsch
Post by Wojtek Lerch
As far as I can tell, the standard doesn't explicitly forbid naming types
larger than SIZE_MAX bytes, or even applying sizeof to such types -- it just
describes the semantics of sizeof in a way that is logically impossible for
such types.
It isn't logically impossible, because implementations are required
to meet the specifications only for programs that are strictly
conforming,
I don't think so. "A program that is correct in all other aspects,
operating on correct data, containing unspecified behavior shall be a
correct program and act in accordance with 5.1.2.3." (4#3)
Post by Tim Rentsch
..., which doesn't include any program that does a
sizeof(long[SIZE_MAX]) (when sizeof(long) > 1);
Why not?
Post by Tim Rentsch
for types
whose size is mathematically greater than SIZE_MAX, sizeof
can take advantage of its result being implementation-defined
and yield any size_t value whatsoever.
If that were true, why couldn't sizeof also take advantage of it for types
whose size is less than SIZE_MAX?
Keith Thompson
2009-01-08 16:34:34 UTC
Permalink
Post by Hallvard B Furuseth
Post by Wojtek Lerch
Post by CBFalconer
Post by Keith Thompson
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
You'd think that; but what about sizeof(char[SIZE_MAX][2])?
What about it? Since sizeof shall return the size in bytes, that array
type is an error. At least gcc and sun CC think so, and it makes sense
to me.
[...]

But what kind of error? It's not a syntax error, and I don't see any
constraint that it violates.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
v***@gmail.com
2009-01-08 16:54:14 UTC
Permalink
Post by Wojtek Lerch
You claim that "sizeof returns the size of ANY object".  I see
nothing in the standard that directly supports this claim.  If you
can prove it from the standard, please do so.  I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this.  No exceptions are mentioned, thus it covers all.
You'd think that; but what about sizeof(char[SIZE_MAX][2])?
What about it?  Since sizeof shall return the size in bytes, that array
type is an error.  At least gcc and sun CC think so, and it makes sense
to me.
[...]
But what kind of error?  It's not a syntax error, and I don't see any
constraint that it violates.
The envirnomental limits require the implementation to accept an
object of at least 32767 bytes in C89 and 65535 bytes in C99.
SIZE_MAX (introduced in C99) is guaranteed to be at least 65535.
Therefore, no implementation is required to accept char [SIZE_MAX][2],
because it exceeds environmental limits.
Wojtek Lerch
2009-01-08 16:46:33 UTC
Permalink
Post by v***@gmail.com
Post by Keith Thompson
Post by Hallvard B Furuseth
Post by Wojtek Lerch
but what about sizeof(char[SIZE_MAX][2])?
What about it? Since sizeof shall return the size in bytes, that array
type is an error. At least gcc and sun CC think so, and it makes sense
to me.
But what kind of error? It's not a syntax error, and I don't see any
constraint that it violates.
The envirnomental limits require the implementation to accept an
object of at least 32767 bytes in C89 and 65535 bytes in C99.
That's not quite accurate; implementations are required to accept at
least one *program* that declares an object of that size (among other
things).
Post by v***@gmail.com
SIZE_MAX (introduced in C99) is guaranteed to be at least 65535.
Therefore, no implementation is required to accept char [SIZE_MAX][2],
because it exceeds environmental limits.
But "char[SIZE_MAX][2]" is a type, not an object.
Hallvard B Furuseth
2009-01-08 17:09:12 UTC
Permalink
Post by Wojtek Lerch
Post by v***@gmail.com
The envirnomental limits require the implementation to accept an
object of at least 32767 bytes in C89 and 65535 bytes in C99.
That's not quite accurate; implementations are required to accept at
least one *program* that declares an object of that size (among other
things).
Post by v***@gmail.com
SIZE_MAX (introduced in C99) is guaranteed to be at least 65535.
Therefore, no implementation is required to accept char [SIZE_MAX][2],
because it exceeds environmental limits.
But it's not required to reject it either. It's OK to accept it
provided it behaves in a logically logically impossible way, as Wojtek
pointed out elsewhere...
Post by Wojtek Lerch
But "char[SIZE_MAX][2]" is a type, not an object.
Ow. Thus allowing (complete) types that cannot be instantiated?
Is that a bug or a feature in the standard?
--
Hallvard
Keith Thompson
2009-01-08 19:28:02 UTC
Permalink
Post by v***@gmail.com
Post by Wojtek Lerch
You claim that "sizeof returns the size of ANY object".  I see
nothing in the standard that directly supports this claim.  If you
can prove it from the standard, please do so.  I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this.  No exceptions are mentioned, thus it covers all.
You'd think that; but what about sizeof(char[SIZE_MAX][2])?
What about it?  Since sizeof shall return the size in bytes, that array
type is an error.  At least gcc and sun CC think so, and it makes sense
to me.
[...]
But what kind of error?  It's not a syntax error, and I don't see any
constraint that it violates.
The envirnomental limits require the implementation to accept an
object of at least 32767 bytes in C89 and 65535 bytes in C99.
SIZE_MAX (introduced in C99) is guaranteed to be at least 65535.
Therefore, no implementation is required to accept char [SIZE_MAX][2],
because it exceeds environmental limits.
Even assuming the environmental limit on object size applies to a type
for which no object is declared, that still doesn't imply that an
implementation *must reject* ``sizeof(char[SIZE_MAX][2])''.

In fact, the implementations I've seen do reject it (i.e., issue a
diagnostic and fail to process the translation unit), and I believe
that's the only reasonable behavior. But I don't see how to justify
it based on the normative wording of the standard.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
David R Tribble
2009-01-08 19:48:49 UTC
Permalink
Post by Keith Thompson
Even assuming the environmental limit on object size applies to a type
for which no object is declared, that still doesn't imply that an
implementation *must reject* ``sizeof(char[SIZE_MAX][2])''.
In fact, the implementations I've seen do reject it (i.e., issue a
diagnostic and fail to process the translation unit), and I believe
that's the only reasonable behavior. But I don't see how to justify
it based on the normative wording of the standard.
It seems clear that SIZE_MAX was meant to be the largest
size of any declarable type, since any declarable type can
be an argument of sizeof(). However, it is reasonable to
say that SIZE_MAX was not meant to be taken as a limit
on actual object size. Indeed, it's been pointed out that
calloc() could be used to create objects much larger than
any declarable type (depending on the implementation).

You could probably make a case that the standard does
not place any upper bounds on object size, in fact, and
rightly shouldn't.

Would it be out of line to propose a new standard macro in
<limits.h> (e.g., VAR_SIZE_MAX) that specifies the largest
allocatable object size (independent of sizeof()) supported
by the implementation?

-drt
Francis Glassborow
2009-01-08 20:41:51 UTC
Permalink
Post by David R Tribble
Post by Keith Thompson
Even assuming the environmental limit on object size applies to a type
for which no object is declared, that still doesn't imply that an
implementation *must reject* ``sizeof(char[SIZE_MAX][2])''.
In fact, the implementations I've seen do reject it (i.e., issue a
diagnostic and fail to process the translation unit), and I believe
that's the only reasonable behavior. But I don't see how to justify
it based on the normative wording of the standard.
It seems clear that SIZE_MAX was meant to be the largest
size of any declarable type, since any declarable type can
be an argument of sizeof(). However, it is reasonable to
say that SIZE_MAX was not meant to be taken as a limit
on actual object size. Indeed, it's been pointed out that
calloc() could be used to create objects much larger than
any declarable type (depending on the implementation).
I am unconvinced that it is in any way an error to have an array whose
total size is greater than SIZE_MAX as long as I never use the type in a
context that requires its actual size to be evaluated. Consider:

int main(void){
long array[SIZE_MAX];
for(long long i = 0; i < SIZE_MAX; i++){
array[i] = 0L;
}
return 0;
}

Which part of the C Standard has been violated? The only part that seems
relevant concerns environmental limits, but if the system has the
resources where is the justification for the compiler rejecting the
above code?

IOWs as long as you never look at the size it is OK :-)
CBFalconer
2009-01-08 22:32:37 UTC
Permalink
Francis Glassborow wrote:
... snip ...
Post by Francis Glassborow
I am unconvinced that it is in any way an error to have an array
whose total size is greater than SIZE_MAX as long as I never use
the type in a context that requires its actual size to be
int main(void){
long array[SIZE_MAX];
for(long long i = 0; i < SIZE_MAX; i++){
array[i] = 0L;
}
return 0;
}
Which part of the C Standard has been violated? The only part that
seems relevant concerns environmental limits, but if the system
has the resources where is the justification for the compiler
rejecting the above code?
IOWs as long as you never look at the size it is OK :-)
I maintain that, whenever (sizeof (long) > 1), that is a compile
error.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Wojtek Lerch
2009-01-08 22:46:57 UTC
Permalink
Post by CBFalconer
Post by Francis Glassborow
long array[SIZE_MAX];
I maintain that, whenever (sizeof (long) > 1), that is a compile
error.
We know that you do, but we don't believe that you have demonstrated that to
be true.
CBFalconer
2009-01-09 01:41:40 UTC
Permalink
Post by Wojtek Lerch
Post by CBFalconer
Post by Francis Glassborow
long array[SIZE_MAX];
I maintain that, whenever (sizeof (long) > 1), that is a compile
error.
We know that you do, but we don't believe that you have
demonstrated that to be true.
I have quoted the appropriate portion of the standard. Any other
interpretation involves a contradiction.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
James Kuyper
2009-01-09 04:37:22 UTC
Permalink
Post by CBFalconer
Post by Wojtek Lerch
Post by CBFalconer
Post by Francis Glassborow
long array[SIZE_MAX];
I maintain that, whenever (sizeof (long) > 1), that is a compile
error.
We know that you do, but we don't believe that you have
demonstrated that to be true.
I have quoted the appropriate portion of the standard. Any other
interpretation involves a contradiction.
My interpretation of the relevant words implies that a conforming
implementation of C can

1. reject any declaration that refers to a type bigger than SIZE_MAX, as
exceeding an implementation limit.

2. have calloc(nmemb, size) return a non-null pointer to enough memory
to store an array nmemb objects of the specified size, even if
nmemb*size has a mathematical value that is greater than SIZE_MAX. It
will return sufficient memory for the specified number of objects of the
specified size, even though the amount of memory required is greater
than the value of nmemb*size, interpreted as a C expression rather than
a mathematical one.

Please demonstrate the contradiction that you see in that interpretation.
Wojtek Lerch
2009-01-09 16:04:58 UTC
Permalink
Post by James Kuyper
My interpretation of the relevant words implies that a conforming
implementation of C can
1. reject any declaration that refers to a type bigger than SIZE_MAX, as
exceeding an implementation limit.
Out of curiosity, do you disagree that a conforming implementation can also
accept programs that refer to types bigger than SIZE_MAX but never apply the
sizeof operator to such a type?
jameskuyper
2009-01-09 17:24:00 UTC
Permalink
Post by Wojtek Lerch
Post by James Kuyper
My interpretation of the relevant words implies that a conforming
implementation of C can
1. reject any declaration that refers to a type bigger than SIZE_MAX, as
exceeding an implementation limit.
Out of curiosity, do you disagree that a conforming implementation can also
accept programs that refer to types bigger than SIZE_MAX but never apply the
sizeof operator to such a type?
I can't think of a good reason why an implementation would want to do
that, but I don't see how accepting such a program violates any of the
standard's requirements.
CBFalconer
2009-01-09 23:59:21 UTC
Permalink
Post by jameskuyper
Post by Wojtek Lerch
Post by James Kuyper
My interpretation of the relevant words implies that a conforming
implementation of C can
1. reject any declaration that refers to a type bigger than
SIZE_MAX, as exceeding an implementation limit.
Out of curiosity, do you disagree that a conforming implementation
can also accept programs that refer to types bigger than SIZE_MAX
but never apply the sizeof operator to such a type?
I can't think of a good reason why an implementation would want to
do that, but I don't see how accepting such a program violates any
of the standard's requirements.
It's a fine point, but the types are harmless. They don't create a
problem unless used in a declaration or sizeof. At that point, the
compiler should find an error, if it hasn't already flagged the
type.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Amandil
2009-01-09 18:12:04 UTC
Permalink
Post by James Kuyper
Post by Wojtek Lerch
Post by CBFalconer
    long array[SIZE_MAX];
I maintain that, whenever (sizeof (long) > 1), that is a compile
error.
We know that you do, but we don't believe that you have
demonstrated that to be true.
I have quoted the appropriate portion of the standard.  Any other
interpretation involves a contradiction.
My interpretation of the relevant words implies that a conforming
implementation of C can
1. reject any declaration that refers to a type bigger than
SIZE_MAX, as
exceeding an implementation limit.
That's definitely true. It is also allowed to set both SIZE_MAX and
the maximum size of an object to 65536. However, the standard allows
these two limitations separately: SIZE_MAX in 7.18.3.2, regarding
<stdint.h>, and object size in 5.2.4.1, Translation limits. I has not
been proven, by Chuck or anyone else, that these two values are
related or must be the same. From the lack of any relationship between
those two values - other than that must both be at least 65536 -
mentioned in the standard, the conclusion can be drawn that there
indeed is not any such relationship. As a matter of fact, the maximum
object size may be less than 65536 in a freestanding implementation,
but no such exception exists for SIZE_MAX.

SIZE_MAX is simply the largest possible value to be contained in an
object of type size_t. I suggest that objects such as

int ia[65536];
char ca[250000];

are valid even when size_t is a short (SIZE_MAX = 65536). The result
of sizeof ia or sizeof ca, in such a case is ID, same as in

int i = 100000;
short s = (short) i;

according to 6.3.1.3.3, or whatever the standard says in 6.3.1.3.2
(Can someone please that to me?)
Post by James Kuyper
2. have calloc(nmemb, size) return a non-null pointer to enough memory
to store an array nmemb objects of the specified size, even if
nmemb*size has a mathematical value that is greater than
SIZE_MAX. It
will return sufficient memory for the specified number of objects of the
specified size, even though the amount of memory required is
greater
than the value of nmemb*size, interpreted as a C expression
rather than
a mathematical one.
And memory returned is addressable by array subscrilpt, which is not
necessarily of type size_t, for two resons. One I mentioned above,
the other is that size_t is (or may be) an unsigned integral type,
while an array subscript is required to be of any integer type,
including a negative long long (6.5.2.1.1, by exclusion of any other
constraints).

-- Marty Amandil


I hope I didn't make
Keith Thompson
2009-01-09 18:32:54 UTC
Permalink
Amandil <***@gmail.com> writes:
[...]
Post by Amandil
That's definitely true. It is also allowed to set both SIZE_MAX and
the maximum size of an object to 65536.
[...]

Correction: 65535.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-09 23:54:41 UTC
Permalink
James Kuyper wrote:
... snip ...
Post by James Kuyper
My interpretation of the relevant words implies that a conforming
implementation of C can
1. reject any declaration that refers to a type bigger than
SIZE_MAX, as exceeding an implementation limit.
2. have calloc(nmemb, size) return a non-null pointer to enough
memory to store an array nmemb objects of the specified size, even
if nmemb*size has a mathematical value that is greater than
SIZE_MAX. It will return sufficient memory for the specified number
of objects of the specified size, even though the amount of memory
required is greater than the value of nmemb*size, interpreted as a
C expression rather than a mathematical one.
Please demonstrate the contradiction that you see in that
interpretation.
size_t is specified to be able to specify the size of ANY object.
The maximum value for a size_t item is SIZE_MAX. All calloc has to
do is check that the product of the specifications does not
overflow a size_t, and pass that to malloc. If it does overflow,
simply return NULL.

Also consider that the system has no known means of allocating that
'over SIZE_MAX' space in a continuous block.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Wojtek Lerch
2009-01-09 04:46:37 UTC
Permalink
Post by CBFalconer
Post by Wojtek Lerch
Post by CBFalconer
Post by Francis Glassborow
long array[SIZE_MAX];
I maintain that, whenever (sizeof (long) > 1), that is a compile
error.
We know that you do, but we don't believe that you have
demonstrated that to be true.
I have quoted the appropriate portion of the standard. Any other
interpretation involves a contradiction.
No, you quoted an irrelevant portion of the standard. And you didn't even
explain whether by "compile error" you meant a constraint violation or
something else.
Hallvard B Furuseth
2009-01-09 21:16:13 UTC
Permalink
Post by CBFalconer
Post by Wojtek Lerch
Post by CBFalconer
Post by Francis Glassborow
long array[SIZE_MAX];
I maintain that, whenever (sizeof (long) > 1), that is a compile
error.
We know that you do, but we don't believe that you have
demonstrated that to be true.
I have quoted the appropriate portion of the standard. Any other
interpretation involves a contradiction.
Maybe nobody has has made this clear yet, but the point is that the
standard has no concept of "compile error". It has circumstances
where the compiler is required to issue a diagonstic: For violations
of constraints, syntax rules, and for #error. See C99 5.1.1.3.

That's why people are pointing out that your quoted standard text is not
a constraint. There is indeed a contradiction, but it is in the
standard.

Faced with a requirement to produce an impossible executable, in real
life it makes sense for a compiler to refuse to compile. But that's
another matter.
--
Hallvard
Wojtek Lerch
2009-01-08 21:38:56 UTC
Permalink
Post by David R Tribble
It seems clear that SIZE_MAX was meant to be the largest
size of any declarable type, since any declarable type can
be an argument of sizeof().
To me it's not clear at all. The only thing that seems clear to me is that
the standard forgot to specify what exactly is forbidden and whether it's a
constraint violation or undefined behaviour (or something else, such as
implementation-defined). Perhaps the plan was to make it consistent with
how ptrdiff_t is specifed -- allow types and objects bigger than SIZE_MAX
(just like arrays with more than PTRDIFF_MAX elements are not forbidden),
but make the behaviour of sizeof undefined for types whose size cannot be
represented as a size_t?
Post by David R Tribble
However, it is reasonable to
say that SIZE_MAX was not meant to be taken as a limit
on actual object size. Indeed, it's been pointed out that
calloc() could be used to create objects much larger than
any declarable type (depending on the implementation).
Where does the standard say that char[SIZE_MAX][SIZE_MAX] is not a
declarable type?
CBFalconer
2009-01-08 22:38:39 UTC
Permalink
... snip ...
Post by Wojtek Lerch
However, it is reasonable to say that SIZE_MAX was not meant to
be taken as a limit on actual object size. Indeed, it's been
pointed out that calloc() could be used to create objects much
larger than any declarable type (depending on the implementation).
Where does the standard say that char[SIZE_MAX][SIZE_MAX] is not a
declarable type?
It says sizeof can return the size of a type. But it returns a
size_t, which has a maximum value of SIZE_MAX. This requires that
the declaration be an error, or at least unusable. The latter
means that declaring such an object, or attempting to create it
with calloc, is an error.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Wojtek Lerch
2009-01-08 23:35:40 UTC
Permalink
Post by CBFalconer
Post by Wojtek Lerch
Where does the standard say that char[SIZE_MAX][SIZE_MAX] is not a
declarable type?
It says sizeof can return the size of a type. But it returns a
size_t, which has a maximum value of SIZE_MAX. This requires that
the declaration be an error, or at least unusable.
Unusable as an operand of sizeof, maybe. But it doesn't follow that it must
be unusable for other purposes.
CBFalconer
2009-01-10 00:09:36 UTC
Permalink
Post by Wojtek Lerch
Post by CBFalconer
Post by Wojtek Lerch
Where does the standard say that char[SIZE_MAX][SIZE_MAX] is
not a declarable type?
It says sizeof can return the size of a type. But it returns a
size_t, which has a maximum value of SIZE_MAX. This requires
that the declaration be an error, or at least unusable.
Unusable as an operand of sizeof, maybe. But it doesn't follow
that it must be unusable for other purposes.
No restriction on using it as a number. But size_t is intended to
measure the size of ANY object, which must first be created. That
means the object fits into memory (which may include disk
simulation of memory space). That also means that size_t matches
the addressing capabilities of the computing unit.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Richard
2009-01-08 23:54:26 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Wojtek Lerch
However, it is reasonable to say that SIZE_MAX was not meant to
be taken as a limit on actual object size. Indeed, it's been
pointed out that calloc() could be used to create objects much
larger than any declarable type (depending on the implementation).
Where does the standard say that char[SIZE_MAX][SIZE_MAX] is not a
declarable type?
It says sizeof can return the size of a type. But it returns a
size_t, which has a maximum value of SIZE_MAX. This requires that
the declaration be an error, or at least unusable. The latter
means that declaring such an object, or attempting to create it
with calloc, is an error.
It amuses me that one the self proclaimed Standard Masters is still not
sure how sizeof works. It is a lesson in the complexity of the language
for the rest of us mere mortals. I often wonder how I managed to program
and maintain huge systems for so many years with very high reliability
rates and still be confused as to what a byte versus a char is or
whether sizeof can return a value that might be more than a gatrillion
zillion.
--
I'm not a person who particularly had heros when growing up.
- Dennis Ritchie when asked about the hero worship coming from c.l.c
Tim Rentsch
2009-01-09 07:37:24 UTC
Permalink
Post by Wojtek Lerch
Post by David R Tribble
It seems clear that SIZE_MAX was meant to be the largest
size of any declarable type, since any declarable type can
be an argument of sizeof().
To me it's not clear at all. The only thing that seems clear to me is that
the standard forgot to specify what exactly is forbidden and whether it's a
constraint violation or undefined behaviour (or something else, such as
implementation-defined). Perhaps the plan was to make it consistent with
how ptrdiff_t is specifed -- allow types and objects bigger than SIZE_MAX
(just like arrays with more than PTRDIFF_MAX elements are not forbidden),
but make the behaviour of sizeof undefined for types whose size cannot be
represented as a size_t?
An overly large type (or object) is not forbidden (by the Standard -
it may be forbidden by an implementation), nor did the Standard forget
to say how to deal with the apparent inconsistency. In particular,
the result of sizeof is implementation-defined; 6.5.3.4 p 4.

The result of sizeof being implementation-defined is the loophole
that allows implementations to accept overly large types without
being forced into a logical inconsistency.

So, for example, an implementation could have SIZE_MAX == 65536,
and sizeof (char [2][65536]) == 12, yet still be a conforming
implementation, because no strictly conforming program can do
sizeof on a type or an object whose mathematical size is
more than 65535.
Wojtek Lerch
2009-01-09 15:22:48 UTC
Permalink
Post by Tim Rentsch
An overly large type (or object) is not forbidden (by the Standard -
it may be forbidden by an implementation), nor did the Standard forget
to say how to deal with the apparent inconsistency. In particular,
the result of sizeof is implementation-defined; 6.5.3.4 p 4.
The result of sizeof being implementation-defined is the loophole
that allows implementations to accept overly large types without
being forced into a logical inconsistency.
No, sizeof being implementation-defined does not mean that the
implementation is free to ignore the requirement that sizeof must return the
size of the type, or any other requirements that affect sizes of objects.
All it means is that implementations can decide what sizes its types are --
but other requirements, such as the size of a structure being no less than
the sum of its members, still must be satisfied.
Post by Tim Rentsch
So, for example, an implementation could have SIZE_MAX == 65536,
and sizeof (char [2][65536]) == 12, yet still be a conforming
implementation, because no strictly conforming program can do
sizeof on a type or an object whose mathematical size is
more than 65535.
Why is this program not strictly conforming:

#include <stddef.h>
#include <limits.h>
int main( void ) {
(void) sizeof( char[ SIZE_MAX ][ 2 ] );
return 0;
}
Keith Thompson
2009-01-09 15:25:04 UTC
Permalink
Tim Rentsch <***@alumnus.caltech.edu> writes:
[...]
Post by Tim Rentsch
An overly large type (or object) is not forbidden (by the Standard -
it may be forbidden by an implementation), nor did the Standard forget
to say how to deal with the apparent inconsistency. In particular,
the result of sizeof is implementation-defined; 6.5.3.4 p 4.
The result of sizeof being implementation-defined is the loophole
that allows implementations to accept overly large types without
being forced into a logical inconsistency.
So, for example, an implementation could have SIZE_MAX == 65536,
and sizeof (char [2][65536]) == 12, yet still be a conforming
implementation, because no strictly conforming program can do
sizeof on a type or an object whose mathematical size is
more than 65535.
I disagree.

6.5.3.4p2 says:

The sizeof operator yields the size (in bytes) of its operand ...

6.5.3.4p4 says:

The value of the result is implementation-defined, and its type
(an unsigned integer type) is size_t, defined in <stddef.h> (and
other headers).

The second statement doesn't override or contradict the first.
*Both* must be true.

The requirements of the standard do not just apply to strictly
conforming programs. 4p3:

A program that is correct in all other aspects, operating on
correct data, containing unspecified behavior shall be a correct
program and act in accordance with 5.1.2.3.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Hallvard B Furuseth
2009-01-09 21:57:55 UTC
Permalink
Post by Tim Rentsch
The result of sizeof being implementation-defined is the loophole
that allows implementations to accept overly large types without
being forced into a logical inconsistency.
Adding to the other "not so" replies: Implementation-defined
means the implementation may choose between some options, not
that it may do whatever it pleases. From C99:

3.4.1 implementation-defined behavior: unspecified behavior
where each implementation documents how the choice is made.

3.4.4 unspecified behavior: behavior where this International
Standard provides two or more possibilities and imposes no
further requirements on which is chosen in any instance.
--
Hallvard
Tim Rentsch
2009-01-09 08:38:22 UTC
Permalink
Post by David R Tribble
Post by Keith Thompson
Even assuming the environmental limit on object size applies to a type
for which no object is declared, that still doesn't imply that an
implementation *must reject* ``sizeof(char[SIZE_MAX][2])''.
In fact, the implementations I've seen do reject it (i.e., issue a
diagnostic and fail to process the translation unit), and I believe
that's the only reasonable behavior. But I don't see how to justify
it based on the normative wording of the standard.
It seems clear that SIZE_MAX was meant to be the largest
size of any declarable type, since any declarable type can
be an argument of sizeof().
I disagree. The wording in 6.5.3.4 p 4

The value of the result is implementation-defined, and its type (an
unsigned integer type) is size_t, defined in <stddef.h> (and other
headers).

suggests that the Standard means to leave the decision about
what constitutes the largest size of any declarable type
be left up to the implementation (subject to the restriction
that it be at least 65535).
Post by David R Tribble
However, it is reasonable to
say that SIZE_MAX was not meant to be taken as a limit
on actual object size. Indeed, it's been pointed out that
calloc() could be used to create objects much larger than
any declarable type (depending on the implementation).
You could probably make a case that the standard does
not place any upper bounds on object size, in fact, and
rightly shouldn't.
Indeed, it does not.
Post by David R Tribble
Would it be out of line to propose a new standard macro in
<limits.h> (e.g., VAR_SIZE_MAX) that specifies the largest
allocatable object size (independent of sizeof()) supported
by the implementation?
Proposing it is surely okay, but if the proposal is going to go
anywhere it needs support from a strong motivating argument. I
myself don't see any really strong motivation to have it (and
conversely do see objections that would need to be overcome).
It seems like too much I for too little R.
CBFalconer
2009-01-08 22:27:22 UTC
Permalink
Keith Thompson wrote:
... snip ...
Post by Keith Thompson
In fact, the implementations I've seen do reject it (i.e., issue
a diagnostic and fail to process the translation unit), and I
believe that's the only reasonable behavior. But I don't see how
to justify it based on the normative wording of the standard.
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Keith Thompson
2009-01-08 22:34:30 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
In fact, the implementations I've seen do reject it (i.e., issue
a diagnostic and fail to process the translation unit), and I
believe that's the only reasonable behavior. But I don't see how
to justify it based on the normative wording of the standard.
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
How does this address my point?

Given the expression:

sizeof (char[SIZE_MAX][2])

the quoted definition for sizeof doesn't imply a constraint violation
or other error. It implies a contradiction *in the standard*.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-09 01:55:27 UTC
Permalink
Post by Keith Thompson
Post by CBFalconer
... snip ...
Post by Keith Thompson
In fact, the implementations I've seen do reject it (i.e., issue
a diagnostic and fail to process the translation unit), and I
believe that's the only reasonable behavior. But I don't see how
to justify it based on the normative wording of the standard.
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
How does this address my point?
sizeof (char[SIZE_MAX][2])
the quoted definition for sizeof doesn't imply a constraint
violation or other error. It implies a contradiction *in the
standard*.
sizeof measures the size of objects, or the type definition that
will be used in constructing an object. Notice the first sentence
of para. 4 below.

6.2.4 Storage durations of objects

... snip ...

[#4] For such an object that does not have a variable length |
array type, storage is guaranteed to be reserved for a new
instance of the object on each entry into the block with
which it is associated; the initial value of the object is
indeterminate. If an initialization is specified for the
object, it is performed each time the declaration is reached
in the execution of the block; otherwise, the value becomes
indeterminate each time the declaration is reached. Storage
for the object is no longer guaranteed to be reserved when
execution of the block ends in any way. (Entering an
enclosed block or calling a function suspends, but does not
end, execution of the current block.)
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Keith Thompson
2009-01-09 02:25:06 UTC
Permalink
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
... snip ...
Post by Keith Thompson
In fact, the implementations I've seen do reject it (i.e., issue
a diagnostic and fail to process the translation unit), and I
believe that's the only reasonable behavior. But I don't see how
to justify it based on the normative wording of the standard.
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
[#2] The sizeof operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type. The size is determined from the type of the
operand. The result is an integer. If the type of the
operand is a variable length array type, the operand is
evaluated; otherwise, the operand is not evaluated and the
result is an integer constant.
How does this address my point?
sizeof (char[SIZE_MAX][2])
the quoted definition for sizeof doesn't imply a constraint
violation or other error. It implies a contradiction *in the
standard*.
sizeof measures the size of objects, or the type definition that
will be used in constructing an object.
sizeof yields the size of a *type*, either the type of the given
expression or the type whose name is given in parentheses.
Post by CBFalconer
Notice the first sentence
of para. 4 below.
6.2.4 Storage durations of objects
... snip ...
[#4] For such an object that does not have a variable length |
array type, storage is guaranteed to be reserved for a new
instance of the object on each entry into the block with
which it is associated; the initial value of the object is
indeterminate.
[...]

Huh?? What on Earth does that have to do with what we're discussing?

We were talking about the expression
sizeof (char[SIZE_MAX][2])
not about any object.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Wojtek Lerch
2009-01-09 04:47:00 UTC
Permalink
Post by CBFalconer
sizeof measures the size of objects, or the type definition that
will be used in constructing an object.
No, sizeof measures the size of types. If the operand is a type, it doesn't
matter whether that type is used in constructing an object enywhere in the
program. If the operand is an expression, only its type matters; whether
the expression designates an object or not is irrelevant.
jameskuyper
2009-01-09 00:05:16 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
In fact, the implementations I've seen do reject it (i.e., issue
a diagnostic and fail to process the translation unit), and I
believe that's the only reasonable behavior. But I don't see how
to justify it based on the normative wording of the standard.
You're earlier answer failed to show any connection between the
section of the standard that you cited and the conclusions that you
mistakenly derived from it.
Flash Gordon
2009-01-08 00:19:52 UTC
Permalink
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
[...]
I claim that calloc didn't really succeed. It just converted the
^^^^^^
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
total size requested using the usual unsigned conversions. It
returned a pointer to a physical object, which was NOT (SIZE_MAX *
2) big. It can't be, since no object can exceed SIZE_MAX. THIS IS
NOT A TYPE. THIS calloc IS FAULTY.
You misunderstood my example. In my hypothetical implementation,
calloc() *did* succeed. It returned a pointer to an object whose
^^^^^^^^^^^^^^^^^^^^^^
Post by CBFalconer
Post by Keith Thompson
Post by CBFalconer
size exceeds SIZE_MAX bytes.
You assert that "no object can exceed SIZE_MAX". I see no *direct*
statement of this in the standard. If there is one, surely you can
provide a citation. (You don't get to just make up rules like this.)
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object. The type returned by sizeof is size_t (which must
be capable of holding that result). SIZE_MAX is the maximum value
of a size_t value. These facts suffice to prove that no object can
exceed SIZE_MAX in size.
I have cross-posted to comp.std.c for further resolution, if any.
One more time. The argument to sizeof is either a parenthesized type
name or an expression. sizeof does not, in general, compute the size
of an object. In particular, an object created by calloc cannot be
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Post by CBFalconer
Post by Keith Thompson
named by an expression, and therefore cannot be an operand of sizeof.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Post by CBFalconer
Post by Keith Thompson
You claim that "sizeof returns the size of ANY object". I see
nothing in the standard that directly supports this claim. If you
can prove it from the standard, please do so. I'm not interested
in any response that doesn't include one or more specific citations
from the standard.
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
<snip>

Is irrelevant since there is no way to make the object created by calloc
the operand of sizeof. I'm sure this point has been made already but you
seem to have missed it.
--
Flash Gordon
CBFalconer
2009-01-08 22:41:43 UTC
Permalink
... snip ...
Post by Flash Gordon
Post by CBFalconer
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
<snip>
Is irrelevant since there is no way to make the object created by
calloc the operand of sizeof. I'm sure this point has been made
already but you seem to have missed it.
No, you have missed that if calloc returned a non-NULL, calloc is
in error.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Keith Thompson
2009-01-08 23:05:20 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Flash Gordon
Post by CBFalconer
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
<snip>
Is irrelevant since there is no way to make the object created by
calloc the operand of sizeof. I'm sure this point has been made
already but you seem to have missed it.
No, you have missed that if calloc returned a non-NULL, calloc is
in error.
Nobody has missed that; you've been claiming it repeatedly. What
we're missing is your demonstration that it's a correct statement.

I assert that, in a conforming implementation, calloc(SIZE_MAX, 2) may
return a non-null pointer which points to the beginning of an
anonymous object whose size is SIZE_MAX*2 bytes. In my opinion, the
standard should be modified so that this is *not* possible, i.e., so
that an object larger than SIZE_MAX bytes is disallowed.

In practice, if an implementation exists for which calloc(SIZE_MAX, 2)
can succeed, the problem is not in the implementation's calloc() but
in its definition of SIZE_MAX; the implementation *should* IMHO make
size_t large enough to hold the largest possible size of any object
that can be created. But I see nothing in the standard that directly
supports this. (The strlen() argument is almost convincing, but it's
uncomfortably indirect.)

And, in practice, I doubt that an implementation exists on which
calloc(SIZE_MAX, 2) returns a non-null pointer. If there is no such
implementation, that would make it easier to revise the standard to
disallow it.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-09 02:02:11 UTC
Permalink
... snip ...
Post by Keith Thompson
Post by CBFalconer
No, you have missed that if calloc returned a non-NULL, calloc is
in error.
Nobody has missed that; you've been claiming it repeatedly. What
we're missing is your demonstration that it's a correct statement.
I assert that, in a conforming implementation, calloc(SIZE_MAX, 2)
may return a non-null pointer which points to the beginning of an
anonymous object whose size is SIZE_MAX*2 bytes. In my opinion, the
standard should be modified so that this is *not* possible, i.e., so
that an object larger than SIZE_MAX bytes is disallowed.
No. Remember that these things are all measured and specified by a
size_t variable. size_t is an unsigned integer, and follows the
wraparound rules for unsigned. Multiplying a size_t by a size_t
cannot ever result in a value larger than SIZE_MAX. It can result
in a much smaller value.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Keith Thompson
2009-01-09 02:40:39 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Keith Thompson
Post by CBFalconer
No, you have missed that if calloc returned a non-NULL, calloc is
in error.
Nobody has missed that; you've been claiming it repeatedly. What
we're missing is your demonstration that it's a correct statement.
I assert that, in a conforming implementation, calloc(SIZE_MAX, 2)
may return a non-null pointer which points to the beginning of an
anonymous object whose size is SIZE_MAX*2 bytes. In my opinion, the
standard should be modified so that this is *not* possible, i.e., so
that an object larger than SIZE_MAX bytes is disallowed.
No.
Yes.
Post by CBFalconer
Remember that these things are all measured and specified by a
size_t variable.
What "variable"? Do you mean an object of type size_t? Or do you
mean a value of type size_t?

And where does the standard say that the size of an object must be
able to be represented as a value of type size_t? (Please don't quote
the standard's definition of sizeof again.)
Post by CBFalconer
size_t is an unsigned integer, and follows the
wraparound rules for unsigned. Multiplying a size_t by a size_t
cannot ever result in a value larger than SIZE_MAX. It can result
in a much smaller value.
When I wrote SIZE_MAX*2, I didn't intend the multiplication to be done
using C's unsigned wraparound semantics. I meant that the object has
a size in bytes twice as large as SIZE_MAX. For example, if
SIZE_MAX==65535, the object has a size of 131070 bytes.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Flash Gordon
2009-01-08 23:09:22 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Flash Gordon
Post by CBFalconer
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
<snip>
Is irrelevant since there is no way to make the object created by
calloc the operand of sizeof. I'm sure this point has been made
already but you seem to have missed it.
No, you have missed that if calloc returned a non-NULL, calloc is
in error.
I had not miss you claiming this. However, as was pointed out last time
you claimed this there is nothing in the C standard saying it is an
error *if* the implementation succeeds in allocating a block of the
correct size and returns a pointer to it. Your quote of the definition
of sizeof does not support your claim for this since you cannot apply
sizeof to the block.
--
Flash Gordon
CBFalconer
2009-01-09 02:08:06 UTC
Permalink
... snip ...
Post by Flash Gordon
Post by CBFalconer
No, you have missed that if calloc returned a non-NULL, calloc
is in error.
I had not miss you claiming this. However, as was pointed out
last time you claimed this there is nothing in the C standard
saying it is an error *if* the implementation succeeds in
allocating a block of the correct size and returns a pointer to
it. Your quote of the definition of sizeof does not support your
claim for this since you cannot apply sizeof to the block.
See my reply to Keith Thompson. You can't legally get calloc to
create anything larger than SIZE_MAX, because you can't specify
such a value. The size_t operands are unsigned integers and follow
the rules for unsigned overflows etc.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Keith Thompson
2009-01-09 02:51:00 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Flash Gordon
Post by CBFalconer
No, you have missed that if calloc returned a non-NULL, calloc
is in error.
I had not miss you claiming this. However, as was pointed out
last time you claimed this there is nothing in the C standard
saying it is an error *if* the implementation succeeds in
allocating a block of the correct size and returns a pointer to
it. Your quote of the definition of sizeof does not support your
claim for this since you cannot apply sizeof to the block.
See my reply to Keith Thompson. You can't legally get calloc to
create anything larger than SIZE_MAX, because you can't specify
such a value. The size_t operands are unsigned integers and follow
the rules for unsigned overflows etc.
Incorrect. Read the standard's description of calloc(). It doesn't
say the two arguments are multiplied.

Consider an implementation where size_t is 16 bits, with
SIZE_MAX==65535. Then SIZE_MAX * SIZE_MAX, after wraparound, yields a
result of 1. (The same happens with a 32-bit size_t.) By your
argument the expression

calloc(SIZE_MAX, SIZE_MAX)

must attempt to allocate just 1 byte. But an implementation that did
that would violate the standard's requirements for calloc(), which
I'll leave you to look up for yourself.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
CBFalconer
2009-01-10 00:16:16 UTC
Permalink
Keith Thompson wrote:
... snip ...
Post by Keith Thompson
Consider an implementation where size_t is 16 bits, with
SIZE_MAX==65535. Then SIZE_MAX * SIZE_MAX, after wraparound,
yields a result of 1. (The same happens with a 32-bit size_t.)
By your argument the expression
calloc(SIZE_MAX, SIZE_MAX)
must attempt to allocate just 1 byte. But an implementation
that did that would violate the standard's requirements for
calloc(), which I'll leave you to look up for yourself.
No. calloc should check that the multiplication does not overflow
before making any attempt to allocate memory. On overflow, return
NULL. Otherwise, call malloc. That's all that is required.
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Flash Gordon
2009-01-09 21:06:31 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Flash Gordon
Post by CBFalconer
No, you have missed that if calloc returned a non-NULL, calloc
is in error.
I had not miss you claiming this. However, as was pointed out
last time you claimed this there is nothing in the C standard
saying it is an error *if* the implementation succeeds in
allocating a block of the correct size and returns a pointer to
it. Your quote of the definition of sizeof does not support your
claim for this since you cannot apply sizeof to the block.
See my reply to Keith Thompson. You can't legally get calloc to
create anything larger than SIZE_MAX, because you can't specify
such a value.
Yes you can as has already been shown in this thread. For one argument
to calloc you pass SIZE_MAX and for the other argument any value greater
than one. Other argument combinations will also achieve the same result.
Post by CBFalconer
The size_t operands are unsigned integers and follow
the rules for unsigned overflows etc.
Irrelevant unless you can show somewhere in the specification for size_t
that the standard requires that calloc perform a multiplication of its
two parameters using the size_t type. Hint, it doesn't.

If you want to say something cannot be done legally you need to provide
a quote from the standard that proves it. The definition of sizeof has
already been demonstrated to NOT be such relevant.
--
Flash Gordon
jameskuyper
2009-01-09 00:09:46 UTC
Permalink
Post by CBFalconer
... snip ...
Post by Flash Gordon
Post by CBFalconer
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
<snip>
Is irrelevant since there is no way to make the object created by
calloc the operand of sizeof. I'm sure this point has been made
already but you seem to have missed it.
No, you have missed that if calloc returned a non-NULL, calloc is
in error.
That's circular; you're being asked to defend that conclusion; you
can't use it as a premise in your argument that's supposed to
demonstrate the correctness of that conclusion.

If you can't demonstrate a way to apply sizeof to the entire object
allocated by calloc(), you can't use the requirements imposed on
sizeof to constrain the behavior of calloc().
Tim Rentsch
2009-01-09 08:50:10 UTC
Permalink
Post by jameskuyper
Post by CBFalconer
... snip ...
Post by Flash Gordon
Post by CBFalconer
How about this. No exceptions are mentioned, thus it covers all.
6.5.3.4 The sizeof operator
... snip ...
Semantics
<snip>
Is irrelevant since there is no way to make the object created by
calloc the operand of sizeof. I'm sure this point has been made
already but you seem to have missed it.
No, you have missed that if calloc returned a non-NULL, calloc is
in error.
That's circular; you're being asked to defend that conclusion; you
can't use it as a premise in your argument that's supposed to
demonstrate the correctness of that conclusion.
If you can't demonstrate a way to apply sizeof to the entire object
allocated by calloc(), you can't use the requirements imposed on
sizeof to constrain the behavior of calloc().
In fact we can prove that there is no such demonstration. There can't
be a way to use sizeof on an object returned from calloc(), because
allocated objects have no declared type, and sizeof works on types.

Of course, it's possible to use sizeof on a pointer that (we think)
points to the object returned by calloc(), but that's not the same as
using sizeof on the allocated object itself.
James Kuyper
2009-01-09 12:26:00 UTC
Permalink
...
Post by Tim Rentsch
Post by jameskuyper
If you can't demonstrate a way to apply sizeof to the entire object
allocated by calloc(), you can't use the requirements imposed on
sizeof to constrain the behavior of calloc().
In fact we can prove that there is no such demonstration. There can't
be a way to use sizeof on an object returned from calloc(), because
allocated objects have no declared type, and sizeof works on types.
That is not, in itself, a problem. Allocated objects can have an
effective type (6.5p6), even if they have no declared type. However, and
in this we are apparently in agreement, there's no way to apply sizeof
Post by Tim Rentsch
... use sizeof on a pointer that (we think)
points to the object returned by calloc(), but that's not the same as
using sizeof on the allocated object itself.
Richard Tobin
2009-01-07 23:06:31 UTC
Permalink
Post by CBFalconer
I see no reason for a 'direct' statement. sizeof returns the size
of ANY object.
It returns the size of any object that you can give as an argument to
sizeof(). It also returns the size of any type you can give as an
argument to sizeof(). You can't give the object allocated by calloc()
to sizeof(), because all you have is a void * pointer, rather than the
allocated object itself. To give sizeof() the object itself, you have
to use a cast or a declared variable, so what it boils down to is that
you can give sizeof() any object that you can write the type of. So
the ability of calloc() to return very large objects isn't any different
from the fact that you can write down a type name that is too large
to fit in a size_t.

Since there are names for types that don't fit in a size_t, the
possibility of calloc() (or anything else) returning excessively
large objects doesn't introduce any new problem.

-- Richard
--
Please remember to mention me / in tapes you leave behind.
Loading...