Comments 'ok'?

C

carl.feynman

Are the comments in this c99 code 'reasonable', i.e., without using
excessive prose, are they ok?

#include <stdio.h>

void f(char * p)
{
// Do we know anything about p - other than p might point to a
char? NO.
//
// Could it be a single char, an unitialised pointer, an illegal
pointer
// an array of char, anything? YES!
//
// Do we know if we can legally alter what p point to? NO.
//
// Do we know the size of p [the arry it might point to]? No - we
know
// that p is sizeof(char *), but we have no other information -
all we're
// passed is a char * - we haven't passed an array as anything
here can
// tell!

// This test in itself doesn't mean p is ok.
//
if(p)
printf("%c\n", *p);
}

int main(void)
{
char ch1[] = "abc";

char * ch2 = "abc";

// Straight forward cases:

f(ch1); // array degrades to a pointer to first elem of ch1.

f(ch2); // could argue -ditto- or not depending on your pedantry-
level.
// depending upon the same we could also say that this
degrades to
// const char * ;, or even perhaps const char const * ;

f(&"abc"[0]); // similar to the literal * case. No ch1/2 object
involved.

f(&0["abc"]); // similar to the literal * case + a silly thing
really.
// No ch1/2 object involved.


f(&ch1[0]); // same as f(ch1);

f(&ch2[0]); // same as f(ch2);

f((char *)0); // we can lie our heads off if we like - no char
now!

return 0;
}
 
R

Richard Heathfield

(e-mail address removed) said:
Are the comments in this c99 code 'reasonable', i.e., without using
excessive prose, are they ok?

As you will see, the // style, combined with typical Usenet wrapping, has
ensured that almost all the comments are broken. That aside, however,
let's look at what they actually say:
#include <stdio.h>

void f(char * p)
{
// Do we know anything about p - other than p might point to a
char? NO.
Right.

//
// Could it be a single char, an unitialised pointer, an illegal
pointer
// an array of char, anything? YES!
Right.

//
// Do we know if we can legally alter what p point to? NO.
Right.

//
// Do we know the size of p [the arry it might point to]? No - we
know
// that p is sizeof(char *), but we have no other information -
all we're
// passed is a char * - we haven't passed an array as anything
here can
// tell!
Right.


// This test in itself doesn't mean p is ok.
//
if(p)
Right.

printf("%c\n", *p);
}

int main(void)
{
char ch1[] = "abc";

char * ch2 = "abc";

// Straight forward cases:

f(ch1); // array degrades to a pointer to first elem of ch1.
Right.


f(ch2); // could argue -ditto- or not depending on your pedantry-
level.

Right. :)
// depending upon the same we could also say that this
degrades to
// const char * ;, or even perhaps const char const * ;

No; rather, ch2 points to the first character in an array that you're not
allowed to modify. That, alas, doesn't mean it's const.
f(&"abc"[0]); // similar to the literal * case. No ch1/2 object
involved.
Right.


f(&0["abc"]); // similar to the literal * case + a silly thing
really.
Right.

// No ch1/2 object involved.
Right.



f(&ch1[0]); // same as f(ch1);
Right.


f(&ch2[0]); // same as f(ch2);
Right.


f((char *)0); // we can lie our heads off if we like - no char
now!

Right.

You scored (N-1) / N for content, and about 4 for presentation. :)
 
C

carl.feynman

Thanks for the rapid reply Richard - and sorry for the // style muck.
Never before posted via such an interface (as I'm having to use).
No; rather, ch2 points to the first character in an array that you're not
allowed to modify. That, alas, doesn't mean it's const.

Do you mean that if it were actually 'const'; a mechanism would
somehow be - should be - invoked to protect any possible modification
(so, it's not const - as nothing of the sort actually happens)? Or,
that if I could quiz my compiler, and ask it to produce type
information (as it sees it!), the compiler would never consider the
expression has any sort of const qualification implied? Or neither of
these two? Don't know if I've worded my query right here - sorry!

(e-mail address removed) said:
Are the comments in this c99 code 'reasonable', i.e., without using
excessive prose, are they ok?

As you will see, the // style, combined with typical Usenet wrapping, has
ensured that almost all the comments are broken. That aside, however,
let's look at what they actually say:


#include <stdio.h>
void f(char * p)
{
// Do we know anything about p - other than p might point to a
char? NO.
Right.

//
// Could it be a single char, an unitialised pointer, an illegal
pointer
// an array of char, anything? YES!
Right.

//
// Do we know if we can legally alter what p point to? NO.
Right.

//
// Do we know the size of p [the arry it might point to]? No - we
know
// that p is sizeof(char *), but we have no other information -
all we're
// passed is a char * - we haven't passed an array as anything
here can
// tell!
Right.



// This test in itself doesn't mean p is ok.
//
if(p)
Right.

printf("%c\n", *p);
}
int main(void)
{
char ch1[] = "abc";
char * ch2 = "abc";
// Straight forward cases:
f(ch1); // array degrades to a pointer to first elem of ch1.
Right.



f(ch2); // could argue -ditto- or not depending on your pedantry-
level.

Right. :)
// depending upon the same we could also say that this
degrades to
// const char * ;, or even perhaps const char const * ;

No; rather, ch2 points to the first character in an array that you're not
allowed to modify. That, alas, doesn't mean it's const.
f(&"abc"[0]); // similar to the literal * case. No ch1/2 object
involved.
Right.



f(&0["abc"]); // similar to the literal * case + a silly thing
really.
Right.

// No ch1/2 object involved.
Right.



f(&ch1[0]); // same as f(ch1);
Right.



f(&ch2[0]); // same as f(ch2);
Right.



f((char *)0); // we can lie our heads off if we like - no char
now!

Right.

You scored (N-1) / N for content, and about 4 for presentation. :)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
E

Eric Sosman

Richard said:
(e-mail address removed) said:


Right.

I don't see how `p' can be "an uninitialized pointer,"
since the act of calling a function initializes all the
function's parameters to the supplied argument values.

True, the supplied argument "value" may have been dodgy
and the resulting undefined behavior may have caused `p' to
be initialized with something strange, but I think we must
consider `p' itself as being "not uninitialized" (double
negative intentional).
 
B

Ben Pfaff

Are the comments in this c99 code 'reasonable', i.e., without using
excessive prose, are they ok?

No. They're far too long to be reasonable. Also, word-wrapping
//-style comments breaks them, so that the code no longer compiles.
 
C

carl.feynman

That's really what I was getting at, when I said 'reasonable', i.e.,
the wording might be ambiguous, and open to debate/interpretation;
but, without getting into 'word knots', is it a reasonable way to
express the problem/what's-happening?
 
R

Richard Heathfield

(e-mail address removed) said:
Thanks for the rapid reply Richard - and sorry for the // style muck.
Never before posted via such an interface (as I'm having to use).


Do you mean that if it were actually 'const'; a mechanism would
somehow be - should be - invoked to protect any possible modification
(so, it's not const - as nothing of the sort actually happens)? Or,
that if I could quiz my compiler, and ask it to produce type
information (as it sees it!), the compiler would never consider the
expression has any sort of const qualification implied? Or neither of
these two? Don't know if I've worded my query right here - sorry!

A string literal containing N characters has type "array of N + 1 char",
and has static storage duration. It isn't const, but you're not allowed to
modify it.

If a function takes const char *, it is making an implicit promise that it
won't modify the data pointed to by that pointer. Of course, it could
cheat by using a cast:

void foo(const char *safe_as_houses)
{
char *burn_the_house = (char *)safe_as_houses;
*burn_the_house = 'X';
}

but the behaviour of such code is undefined (see 3.5.3 of C89 or 6.7.3(5)
of C99). Without the cast, you get a diagnostic message (which is the
protection you were hoping for).
 
C

carl.feynman

A string literal containing N characters has type "array of N + 1 char",
and has static storage duration. It isn't const, but you're not allowed to
modify it.

If a function takes const char *, it is making an implicit promise that it
won't modify the data pointed to by that pointer. Of course, it could
cheat by using a cast:

void foo(const char *safe_as_houses)
{
char *burn_the_house = (char *)safe_as_houses;
*burn_the_house = 'X';

}

but the behaviour of such code is undefined (see 3.5.3 of C89 or 6.7.3(5)
of C99). Without the cast, you get a diagnostic message (which is the
protection you were hoping for).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
 
E

Eric Sosman

post.
top-
don't
Please

That's really what I was getting at, when I said 'reasonable', i.e.,
the wording might be ambiguous, and open to debate/interpretation;
but, without getting into 'word knots', is it a reasonable way to
express the problem/what's-happening?

Since most of the context seems to have been snipped
away, here's a synopsis: Given a function `void f(char *p)',
what can be said about `p' and about what it points to (if
it points to anything). One of the questions was

Could it be a single char, an unitialised pointer,
an illegal pointer an array of char, anything?

.... and one issue is that "it" is being used to refer to
two different things: the pointer `p', and its target (if
there is one). Here's what I think we can say:

- In a conforming program, `p' will be initialized to
the value of the argument expression provided by the
caller.

- In a well-behaved program, the caller will provide an
argument value that is either a valid pointer to a
char or is a null pointer. Otherwise, the caller
invokes undefined behavior.

- If `p' is non-null, then, it points at a char.

- There may or may not be other chars in the vicinity of
p's target; that's a matter of convention, of
convention, of the "contract" for using f.

- The char p points at may or may not be modifiable. If
other chars are nearby, they may or may not be modifiable.

- `p' itself is modifiable.

- If the program is not well-behaved, very little
can be said and even less of that little is useful.
 
S

santosh

Eric said:
post.
top-
don't
Please



Since most of the context seems to have been snipped
away, here's a synopsis: Given a function `void f(char *p)',
what can be said about `p' and about what it points to (if
it points to anything). One of the questions was

Could it be a single char, an unitialised pointer,
an illegal pointer an array of char, anything?

... and one issue is that "it" is being used to refer to
two different things: the pointer `p', and its target (if
there is one). Here's what I think we can say:

- In a conforming program, `p' will be initialized to
the value of the argument expression provided by the
caller.

- In a well-behaved program, the caller will provide an
argument value that is either a valid pointer to a
char or is a null pointer. Otherwise, the caller
invokes undefined behavior.

Whether a null pointer argument is well behaved depends on the function
doesn't it? If the function expects a non-null pointer, then by
contract, undefined behaviour is invoked if it is called with NULL.
- If `p' is non-null, then, it points at a char.

?

It points at a memory location that will be accessed as a char through
the pointer, but that memory location need not actually contain a
proper char value at all.

BTW, I'm not disagreeing with your point above.
- There may or may not be other chars in the vicinity of
p's target; that's a matter of convention, of
convention, of the "contract" for using f.

- The char p points at may or may not be modifiable. If
other chars are nearby, they may or may not be modifiable.

- `p' itself is modifiable.

- If the program is not well-behaved, very little
can be said and even less of that little is useful.

Yes, this is the most important point from the P.O.V. of standard C.
 
E

Eric Sosman

santosh said:
Whether a null pointer argument is well behaved depends on the function
doesn't it? If the function expects a non-null pointer, then by
contract, undefined behaviour is invoked if it is called with NULL.

The inference is one-way: A well-behaved program will
provide NULL or a valid pointer to a char, but the fact that
such a value is provided does not guarantee that the program
is well-behaved. Sorry if there was any confusion.
?

It points at a memory location that will be accessed as a char through
the pointer, but that memory location need not actually contain a
proper char value at all.

The pointed-to char may or may not already contain anything
useful; it could, in theory, hold a trap representation. But
it occurs to me that I was wrong on another count: a valid and
non-null char* might not point at an actual char, as in

char buff[100];
f(buff + 100); /* valid, non-null, but ... */
 
I

Ian Collins

Are the comments in this c99 code 'reasonable', i.e., without using
excessive prose, are they ok?
They are excessive and add absolutely nothing to the code. Let the code
tell its own story.
 
L

lawrence.jones

Richard Heathfield said:
If a function takes const char *, it is making an implicit promise that it
won't modify the data pointed to by that pointer. Of course, it could
cheat by using a cast:

void foo(const char *safe_as_houses)
{
char *burn_the_house = (char *)safe_as_houses;
*burn_the_house = 'X';
}

but the behaviour of such code is undefined (see 3.5.3 of C89 or 6.7.3(5)
of C99).

It's only undefined if the target of the pointer is actually *defined* as
const. If not, then the behavior is defined (but perverse):

void testfunc(void)
{
char good[10];
const char bad[10];

foo(good); // OK
foo(bad); // undefined behavior
}

-Larry Jones

I always send Grandma a thank-you note right away. ...Ever since she
sent me that empty box with the sarcastic note saying she was just
checking to see if the Postal Service was still working. -- Calvin
 
R

Richard Heathfield

(e-mail address removed) said:
It's only undefined if the target of the pointer is actually *defined* as
const. If not, then the behavior is defined (but perverse)

Oops, you're right. Thank you for the correction.
 
D

David Thompson

(e-mail address removed) said:
void f(char * p)
char ch1[] = "abc";
f(ch1); // array degrades to a pointer to first elem of ch1.

Right.
The standard slang (!) is 'decay'.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 
J

John Bode

Are the comments in this c99 code 'reasonable', i.e., without using
excessive prose, are they ok?

#include <stdio.h>

void f(char * p)
{
// Do we know anything about p - other than p might point to a
char? NO.
//
// Could it be a single char, an unitialised pointer, an illegal
pointer
// an array of char, anything? YES!
//
// Do we know if we can legally alter what p point to? NO.
//
// Do we know the size of p [the arry it might point to]? No - we
know
// that p is sizeof(char *), but we have no other information -
all we're
// passed is a char * - we haven't passed an array as anything
here can
// tell!

// This test in itself doesn't mean p is ok.
//

From a tutorial or educational standpoint, ok. From a production
standpoint, *ugh*:

1. Don't document the obvious. Sanity checks against NULL are common
and obvious bits of code, and as such don't really need an inline
comment. The intent of the code can be made even clearer by expressly
testing against NULL (i.e., if (p != NULL)).

2. Don't be chatty. Inline comments should be direct and to the
point; they should not be discussions of concepts larger than the
lines of code immediately following. The above comments can be
reasonably reduced to "Make sure p isn't NULL; it is assumed that p is
otherwise valid." But again, the comment shouldn't even be
necessary.
if(p)
printf("%c\n", *p);

}

[snip rest]
 
K

Keith Thompson

Richard Heathfield said:
David Thompson said:
(e-mail address removed) said:
void f(char * p)
char ch1[] = "abc";
f(ch1); // array degrades to a pointer to first elem of ch1.

Right.
The standard slang (!) is 'decay'.

The word "decay" does not appear in the Standard.

No, but I don't think Mr. Thompson (no relation) used the word
"standard" generically, not as a reference to the Standard.
Furthermore, "degrade"
and "decay" are near-synonyms (Chambers lists "decompose" as a synonym of
both).

True, but "decay" is the most common (non-Standard) jargon term for
this conversion.
Had I "corrected" Mr Feynman, I would have been guilty of
unwarranted and indeed unjustifiable pickiness.

You would not have been guilty, but you undoubtedly would have been
convicted anyway.
 
K

Keith Thompson

Keith Thompson said:
Richard Heathfield said:
David Thompson said:
On Tue, 25 Mar 2008 17:15:30 +0000, Richard Heathfield

(e-mail address removed) said:

void f(char * p)

char ch1[] = "abc";

f(ch1); // array degrades to a pointer to first elem of ch1.

Right.

The standard slang (!) is 'decay'.

The word "decay" does not appear in the Standard.

No, but I don't think Mr. Thompson (no relation) used the word
"standard" generically, not as a reference to the Standard.
[...]

Whoops, I meant that I *do* think he used the word generically.
 

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,787
Messages
2,569,629
Members
45,330
Latest member
AlvaStingl

Latest Threads

Top