CBFalconer said:
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.
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.
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().