Topic: const or define?


Author: ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe)
Date: 10 Aug 93 04:07:17 GMT
Raw View
In article <KANZE.93Aug5163645@slsvhdt.us-es.sel.de>, kanze@us-es.sel.de (James Kanze) writes:
> ... Davison is completely correct.  Although on all implementations that
> I know of, 'char*' and 'void*' share the same representation, I do not
> believe that this is required.  In any case, the specification for the
> '%p' formatter definitly says that it should be given a 'void*' as
> parameter.

ISO/IEC 9899:1990 Section 6.1.2.5, the paragraph just before the heading
"Examples":
 A pointer to void shall have the same representation
 and alignment requirements as a pointer to a character type.
That takes care of char* and void*.  It goes on to say
 Similarly, pointers to qualified or unqualified versions of
 compatible types shall have the same representation
 and alignment requirements.
That takes care of (void*) and (const void*); the same representation
and alignment requirements they _must_ have.

Section 7.9.6.1, describing printf, says of "p" that
 The argument shall be a pointer to void.
 The value of the pointer is converted ...

For the similar "s" we find
 The argument shall be a pointer to an array of character type.

"character type" means char, signed char, or unsigned char.
Presumably "array" here is describing the object pointed to, not the type
of the pointer.  7.9.6.1 does not explicitly say that
 const char msg[] = "Hello, world!";
 printf("%s\n", msg);
is legal:  this example is exactly parallel to the
 printf("%p", (const void *)x);
case.

I think the answer may perhaps lie in section 7.8.1.2.
After all, printf() is a varargs function.  Programmer-written varargs
functions have to obey the rules of 7.8.1.2 where we are told that for
va_arg(alist, type), the behaviour is undefined if
"there is no next argument, or type is not COMPATIBLE with the type of
the actual next argument (as promoted according to the default argument
promotions)."

On the other hand, while
 const {char,unsigned char,signed char,void} *
must have the same representation and alignment requirements as
       {char,unsigned char,signed char,void} *
matching pairs from these lists are not themselves compatible.
So the answer is _not_ in section 7.8.1.2.

It does seem that the description of printf() might be a little bit
sloppy.  The description of "%n" says
 The argument shall be a pointer to an integer
which does not make clear to me what _kind_ of integer: short, int, long?

I don't myself care all that much about %p, but I would be happier if
passing const char* to %s were as legal as I had always imagined it to be.
--
Richard A. O'Keefe; ok@goanna.cs.rmit.oz.au; RMIT, Melbourne, Australia.




Author: bill@twwells.com (T. William Wells)
Date: 5 Aug 93 06:24:02 GMT
Raw View
In article <23mllc$j84@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
:         In article <KANZE.93Aug3194337@slsvhdt.us-es.sel.de>
: kanze@us-es.sel.de (James Kanze) writes:
: >In article <mTTF8B3w165w@pinetree.org> s_duck@pinetree.org (Dan
: >Mehkeri) writes:
: >|> That's too bad. I'll have to get a refund :)
: >|> Try:
: >|>   const char quack[] = "Ducks rule!";
: >|>   ...
: >|>   printf("%p", &quack);
: >|> and see what the compiler has to say about *that*. On my compiler
: >|> anyways, 'quack' is not a variable. The compiler is quite adamant that it
: >|> is an rvalue!

'quack' is the name of an object of array type. If printf weren't
known to the compiler, it could not complain about the call.
However, if it does know about printf, it could be complaining
that &quack is not of type void*.

: >I believe you wanted to say 'printf( "%p" , quack )', without the '&'
: >operator.  'Quack' is an array, so in expressions, the name 'quack'
: >degenerates to the (constant, non-l-value) address of the first
: >element of the array.

Almost. In an *rvalue* context (one where the value of an
expression is wanted), quack is converted to a pointer to its
first element and is no longer an lvalue. Other places, it is not
converted.

:         'printf( "%p" , quack )' is also incorrect.  (See ANSI X3.159-1989,
: Section 4.9.6.1, Page 135, Lines 1-2.)  The only legal way to do this, to my
: knowledge (which is a little fuzzy on this point -- a clarification might be
: needed), is 'printf( "%p" , (void *) quack )'.

(void*)&quack would also be legal and, on most machines, would
print the same value.

:                                                 (Note that this is violates the
: constness of "quack".)

No it doesn't. The contents of quack aren't accessed so there's
no problem.

:                         (char *) should also work (I think) since (char *) and
: (void *) share the same layout.

Yes.

:         It appears to me that the 'p' flag character implicitly gives fprintf
: and printf the right to go ahead and fiddle with the data pointed to by "quack"

Nonsense. Nowhere does it say that *printf may do this.

: in any way the implementation pleases, including leaving those data in a
: modified state as a side effect of the pointer being "converted for output".  I
: don't see where Section 4.9.6.1 says that an implementation shall not do this.

Methinks you need to go back to grammar school. Clue: the standard
NEVER has to say such things. Else, any function could do
*anything* that wasn't explicitly proscribed. This ought to be
obvious.




Author: bill@twwells.com (T. William Wells)
Date: 5 Aug 93 22:53:51 GMT
Raw View
In article <KANZE.93Aug5163645@slsvhdt.us-es.sel.de> kanze@us-es.sel.de (James Kanze) writes:
:                                     Although on all implementations that
: I know of, 'char*' and 'void*' share the same representation, I do not
: believe that this is required.

See 3.1.2.5, where it says that the two types of pointers must
have the same representation and alignment requirements.




Author: clive@x.co.uk (Clive Feather)
Date: Fri, 6 Aug 1993 08:45:43 GMT
Raw View
In article <KANZE.93Aug5164443@slsvhdt.us-es.sel.de> kanze@us-es.sel.de (James Kanze) writes:
>>> In article <KANZE.93Aug3194337@slsvhdt.us-es.sel.de> kanze@us-es.sel.de (James Kanze) writes:
>>>> In article <mTTF8B3w165w@pinetree.org> s_duck@pinetree.org (Dan Mehkeri) writes:
>>>>> const char quack[] = "Ducks rule!";
>>>>> printf("%p", &quack);
>>>> I believe you wanted to say 'printf( "%p" , quack )', without the '&'
>>>> operator.  'Quack' is an array, so in expressions, the name 'quack'
>>>> degenerates to the (constant, non-l-value) address of the first
>>>> element of the array.
> To quote the C standard (ISO secton 6.2.2.1): "Except when it is the
> operand of the sizeof operator or the unary & operator, or is a
> character string literal used to initialize an array of character
> type, or is a wide string literal used to initialize an array with
> element type compatible with wchar_t, an lvalue that has type "array
> of type" is converted to an expression that has type "pointer to type"
> that points to the initial element of the array obejct and is not an
> lvalue."  So in fact, the presense of the '&' in the original example
> should not change anything.  This would tend to suggest that there is
> a bug in the original poster's compiler.

Wrong.

The expression "quack" has type "array of 12 const char (const char [12])",
and so, in the context of a procedure parameter, decays, via the Rule, to
"pointer to const char (const char *)". However, the expression "&quack"
has type "pointer to array of 12 const char (const char (*) [12])", and this
is not affected by the Rule. On byte-addressed systems, the *value* of
the pointer is likely to be the same. However, the expressions have
different types, and, for example, incrementing a value of the two types
will leave pointers to different places. On systems where byte and word
pointers are different, the two expressions won't even have the same
value.

Having said that much, the compiler doesn't have a prototype for that
parameter. The expression "quack" must have the same representation as
(void *), and so %p should work. The expression "&quack" does not, and
need not even have the correct number of bytes to work.

Where's Chris Torek when you need him ?

--
Clive D.W. Feather     | IXI Ltd (an SCO company) | If you lie to the compiler,
clive@x.co.uk          | Vision Park              | it will get its revenge.
Phone: +44 223 236 555 | Cambridge   CB4 4ZR      |   - Henry Spencer
Fax:   +44 223 236 466 | United Kingdom           |




Author: muzok@microsoft.com (Muzaffer Kal)
Date: 06 Aug 93 18:35:28 GMT
Raw View
In article <23mllc$j84@crchh327.bnr.ca> davisonj@bnr.ca wrote:
>         It appears to me that the 'p' flag character implicitly gives fprintf
> and printf the right to go ahead and fiddle with the data pointed to by "quack"
> in any way the implementation pleases, including leaving those data in a
> modified state as a side effect of the pointer being "converted for output".  I
> don't see where Section 4.9.6.1 says that an implementation shall not do this.
>

Now I don't understand this. How does the compiler know what printf(fprintf) will do
when it sees a %p in first parameter string ? printf is defined to be a variable
parameter function (right ?) and why does the compiler care about what you pass to it
after the first parameter ?

Muzaffer

The views expressed in this message are my own and
in no way reflect the views of Microsoft Corporation.

>
> --
> John Davison, davisonj@ecn.purdue.edu <---- send followups to THIS ADDRESS!!!!!
> (Otherwise your mail will bounce!)  If you work at NT/BNR, please COCOS to
> "John Davison".  The information contained in this article isn't necessarily
> representative of Northern Telecom or BNR.




Author: davisonj@bnr.ca (John M Davison)
Date: 3 Aug 1993 21:34:36 GMT
Raw View
        In article <KANZE.93Aug3194337@slsvhdt.us-es.sel.de>
kanze@us-es.sel.de (James Kanze) writes:
>In article <mTTF8B3w165w@pinetree.org> s_duck@pinetree.org (Dan
>Mehkeri) writes:
>|> That's too bad. I'll have to get a refund :)
>|> Try:
>|>   const char quack[] = "Ducks rule!";
>|>   ...
>|>   printf("%p", &quack);
>|> and see what the compiler has to say about *that*. On my compiler
>|> anyways, 'quack' is not a variable. The compiler is quite adamant that it
>|> is an rvalue!
>
>I believe you wanted to say 'printf( "%p" , quack )', without the '&'
>operator.  'Quack' is an array, so in expressions, the name 'quack'
>degenerates to the (constant, non-l-value) address of the first
>element of the array.

        'printf( "%p" , quack )' is also incorrect.  (See ANSI X3.159-1989,
Section 4.9.6.1, Page 135, Lines 1-2.)  The only legal way to do this, to my
knowledge (which is a little fuzzy on this point -- a clarification might be
needed), is 'printf( "%p" , (void *) quack )'.  (Note that this is violates the
constness of "quack".)  (char *) should also work (I think) since (char *) and
(void *) share the same layout.

        It appears to me that the 'p' flag character implicitly gives fprintf
and printf the right to go ahead and fiddle with the data pointed to by "quack"
in any way the implementation pleases, including leaving those data in a
modified state as a side effect of the pointer being "converted for output".  I
don't see where Section 4.9.6.1 says that an implementation shall not do this.


--
John Davison, davisonj@ecn.purdue.edu <---- send followups to THIS ADDRESS!!!!!
(Otherwise your mail will bounce!)  If you work at NT/BNR, please COCOS to
"John Davison".  The information contained in this article isn't necessarily
representative of Northern Telecom or BNR.




Author: diamond@jit.dec.com (Norman Diamond)
Date: 4 Aug 1993 06:41:41 GMT
Raw View
In article <23mllc$j84@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
>(char *) should also work (I think) since (char *) and
>(void *) share the same layout.

Yes.  (Or at least they used to :-)

>        It appears to me that the 'p' flag character implicitly gives fprintf
>and printf the right to go ahead and fiddle with the data pointed to by "quack"
>in any way the implementation pleases, including leaving those data in a
>modified state as a side effect of the pointer being "converted for output".  I
>don't see where Section 4.9.6.1 says that an implementation shall not do this.

Now you're worrying too much.  The expression   a = b + c   isn't specifically
defined as not modifying b or c, but I think we can assume that definitions
specify what the meaning of a program is and specify what implementations can
do with a program, not allowing other behavior unless the program is undefined.
--
 <<  If this were the company's opinion, I would not be allowed to post it.  >>
A program in conformance will not tend to stay in conformance, because even if
it doesn't change, the standard will.       Force = program size * destruction.
Every technical corrigendum is met by an equally troublesome new defect report.




Author: kanze@us-es.sel.de (James Kanze)
Date: 5 Aug 93 16:36:45
Raw View
In article <23mllc$j84@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:

|>         In article <KANZE.93Aug3194337@slsvhdt.us-es.sel.de>
|> kanze@us-es.sel.de (James Kanze) writes:
|> >In article <mTTF8B3w165w@pinetree.org> s_duck@pinetree.org (Dan
|> >Mehkeri) writes:
|> >|> That's too bad. I'll have to get a refund :)
|> >|> Try:
|> >|>   const char quack[] = "Ducks rule!";
|> >|>   ...
|> >|>   printf("%p", &quack);
|> >|> and see what the compiler has to say about *that*. On my compiler
|> >|> anyways, 'quack' is not a variable. The compiler is quite adamant that it
|> >|> is an rvalue!

|> >I believe you wanted to say 'printf( "%p" , quack )', without the '&'
|> >operator.  'Quack' is an array, so in expressions, the name 'quack'
|> >degenerates to the (constant, non-l-value) address of the first
|> >element of the array.

|>         'printf( "%p" , quack )' is also incorrect.  (See ANSI X3.159-1989,
|> Section 4.9.6.1, Page 135, Lines 1-2.)  The only legal way to do this, to my
|> knowledge (which is a little fuzzy on this point -- a clarification might be
|> needed), is 'printf( "%p" , (void *) quack )'.  (Note that this is violates the
|> constness of "quack".)  (char *) should also work (I think) since (char *) and
|> (void *) share the same layout.

Mr. Davison is completely correct.  Although on all implementations that
I know of, 'char*' and 'void*' share the same representation, I do not
believe that this is required.  In any case, the specification for the
'%p' formatter definitly says that it should be given a 'void*' as
parameter.

Of course, I would normally write:
 cout << (void*)quack ;
In this case, the absense of the cast to 'void*' would result in
completely different semantics.
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung




Author: kanze@us-es.sel.de (James Kanze)
Date: 5 Aug 93 16:44:43
Raw View
In article <CB9wG4.7oH@twwells.com> bill@twwells.com (T. William
Wells) writes:

|> In article <23mllc$j84@crchh327.bnr.ca> davisonj@bnr.ca (John M Davison) writes:
|> :         In article <KANZE.93Aug3194337@slsvhdt.us-es.sel.de>
|> : kanze@us-es.sel.de (James Kanze) writes:
|> : >In article <mTTF8B3w165w@pinetree.org> s_duck@pinetree.org (Dan
|> : >Mehkeri) writes:
|> : >|> That's too bad. I'll have to get a refund :)
|> : >|> Try:
|> : >|>   const char quack[] = "Ducks rule!";
|> : >|>   ...
|> : >|>   printf("%p", &quack);
|> : >|> and see what the compiler has to say about *that*. On my compiler
|> : >|> anyways, 'quack' is not a variable. The compiler is quite adamant that it
|> : >|> is an rvalue!

|> 'quack' is the name of an object of array type. If printf weren't
|> known to the compiler, it could not complain about the call.
|> However, if it does know about printf, it could be complaining
|> that &quack is not of type void*.

|> : >I believe you wanted to say 'printf( "%p" , quack )', without the '&'
|> : >operator.  'Quack' is an array, so in expressions, the name 'quack'
|> : >degenerates to the (constant, non-l-value) address of the first
|> : >element of the array.

|> Almost. In an *rvalue* context (one where the value of an
|> expression is wanted), quack is converted to a pointer to its
|> first element and is no longer an lvalue. Other places, it is not
|> converted.

To quote the C standard (ISO secton 6.2.2.1): "Except when it is the
operand of the sizeof operator or the unary & operator, or is a
character string literal used to initialize an array of character
type, or is a wide string literal used to initialize an array with
element type compatible with wchar_t, an lvalue that has type "array
of type" is converted to an expression that has type "pointer to type"
that points to the initial element of the array obejct and is not an
lvalue."  So in fact, the presense of the '&' in the original example
should not change anything.  This would tend to suggest that there is
a bug in the original poster's compiler.
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung