Null terminated strings: bad or good?

F

Flash Gordon

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

CBFalconer

Tony said:
.... snip ...

Now I'm wondering if I should jettison maintaining the null and
with it C compatibility. Or at least have a separate beast called
CString for the null-terminated encapsulation. Or simply have the
overloaded char* operator null terminate on the fly when
interfacing "legacy code". The latter sounds pretty good. I'll
have to think about that some more, but appears that my string
library is going to be reworked now that this thread of discussion
has me thinking about the concept of null termated strings from a
broader perspective instead of just accepting them without
question. (Sorry for the C++ discussion in c.l.c.).

If you really want a compatible (to asciiz strings) system, build
one with a further special character (when preceded by the excape
char, '\'). Use it to define a zero in the actual string. Retain
the pure zero for the string terminator.

The standard contains a list of used escaped characters, so you can
find another one. You won't be compatible with somebody elses use
of that escape.
 
W

Wojtek Lerch

CBFalconer said:
Wojtek said:
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.
 
R

Richard

CBFalconer said:
Wojtek said:
... snip ...
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.
 
R

Richard

Antoninus Twink said:
Wrong. An expression is a sequence of operators and operands. An object
is a region of data storage. Read the goddamn standard you spend so much
time pushing down people's throats.


Let me be the first of many to tell you that
i ...
is a syntax error.

Even if you replace it by
i;
then since i is uninitialized your program invokes undefined behavior
and might format your hard disk. (Yeah, right...)

According to Heathfield he did that with UB once. So don't mock.
 
R

Richard

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

Richard

CBFalconer said:
Don't forget that there is no 'string' type. Strings are a
particular use of char arrays, which are a type.

Are you seriously telling Nick Keighley and Heathfield not to forget
there is no "string" type?

Where the hell do you get off?!?!?!??!?

I am sure they are both very well aware of this.

I've begun to suspect you might just be a very, very subtle troll.
 
A

Antoninus Twink

According to Heathfield he did that with UB once. So don't mock.

Sorry! Very bad of me...

Of course, if Heathfield said it then it must be true. After all, we all
know that Heathfield never lies - he said so himself.
 
J

jameskuyper

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().
 
A

Antoninus Twink

CBFalconer said:

Where the hell do you get off?!?!?!??!?

I've begun to suspect you might just be a very, very subtle troll.

Nah, I don't think his mind is sharp enough for subtleties like that.

He's just someone so old that his brain has rotted away - if he wasn't
so goddamn annoying about it, it would be tragic to see someone so
completely unaware that they've lost their marbles.
 
J

jameskuyper

CBFalconer said:
See my earlier answer, which was:

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.
 
W

Wojtek Lerch

Richard said:
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?
;-)
 
J

jameskuyper

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

CBFalconer

Keith said:
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.
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).
 
C

CBFalconer

jameskuyper said:
CBFalconer wrote:
.... snip ...


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 *.
 
C

CBFalconer

Wojtek said:
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:

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.
 
R

Richard Tobin

What expression refers to the object -- the entire object --
created by calloc (assuming it returns a non-null pointer)?
*p certainly doesn't.
[/QUOTE]
*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
 
K

Keith Thompson

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,800
Messages
2,569,657
Members
45,414
Latest member
GlycoCareGlycogenControl
Top