473,385 Members | 1,531 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Suffix allowed on expressions?

Hi!

Are suffixes allowed on expressions?

For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL

I found this in a C test at http://www.embedded.com/2000/0005/0005feat2.htm
,
however, I am not able to compile when using this macro (or just the
expression "a = (60 * 60 * 365) UL;").

Where in the standard does it say that it is allowed/not allowed?

It would also be interesting to hear if there are any faults in the
other questions and answers in the test.

BRs!
Jan 2 '08 #1
41 2985
On 2 Jan, 19:07, dspfun <dsp...@hotmail.comwrote:
Hi!

Are suffixes allowed on expressions?

For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL
It should be:
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365) UL
>
I found this in a C test athttp://www.embedded.com/2000/0005/0005feat2.htm
,
however, I am not able to compile when using this macro (or just the
expression "a = (60 * 60 * 365) UL;").
It should be:
(or just the expression statement "a = (60 * 60 * 24 * 365) UL;")

Jan 2 '08 #2
dspfun <ds****@hotmail.comwrites:
Are suffixes allowed on expressions?
No. The suffixes that you are talking about are allowed only on
integer and floating-point constants.
For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL
No. To get the apparently intended effect, you can write
#define SECONDS_PER_YEAR (60UL * 60 * 365)
or
#define SECONDS_PER_YEAR (unsigned long int) (60 * 60 * 365)
--
"All code should be deliberately written for the purposes of instruction.
If your code isn't readable, it isn't finished yet."
--Richard Heathfield
Jan 2 '08 #3
Ben Pfaff <bl*@cs.stanford.eduwrites:
To get the apparently intended effect, you can write
#define SECONDS_PER_YEAR (60UL * 60 * 365)
or
#define SECONDS_PER_YEAR (unsigned long int) (60 * 60 * 365)
Oh, and to get the apparently intended value, you need to
multiply by an additional factor of 24.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,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;}}}
Jan 2 '08 #4
Ben Pfaff <bl*@cs.stanford.eduwrites:
dspfun <ds****@hotmail.comwrites:
>For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL

No. To get the apparently intended effect, you can write
#define SECONDS_PER_YEAR (60UL * 60 * 365)
or
#define SECONDS_PER_YEAR (unsigned long int) (60 * 60 * 365)
The latter can, as I am sure you know, overflow. Since the quiz was
on a site that referenced embedded systems, it would be safer to
assume a minimal max int (if you see what I mean).

To the OP: to illustrate using a cast (which *can* be used in
expressions unlike suffixes) you could write:

#define SECONDS_PER_YEAR ((unsigned long int)60 * 60 * 365)

* is left-associative so all the multiplications must produce unsigned
long int results.

--
Ben.
Jan 2 '08 #5
Keith Thompson <ks***@mib.orgwrites:
[...]
There's a contact address in the article; I'll send him pointers to
your article and my followup.
The e-mail address in the article is obsolete (I think the article is
several years old). I found what appears to be his current address by
searching the embedded.com web site. (I won't post it here; I'm sure
he gets more than enough spam already.)

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 2 '08 #6
Ben Pfaff wrote:
dspfun <ds****@hotmail.comwrites:
>Are suffixes allowed on expressions?

No. The suffixes that you are talking about are allowed only on
integer and floating-point constants.
>For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL

No. To get the apparently intended effect, you can write
#define SECONDS_PER_YEAR (60UL * 60 * 365)
or
#define SECONDS_PER_YEAR (unsigned long int) (60 * 60 * 365)
The second will only work if the expression (60 * 60 * 365) is
within the range of an int. This is doubtful if running on a 16
bit system.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee, Frohe Weihnachten
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com

Jan 2 '08 #7
What about question 12, isn't it implementation specific since the
representation of the basic types are not precisely defined by the
language?

---------------
12. What does the following code output and why?

void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b 6) ? puts("6") : puts("<= 6");
}

Answer:
This question tests whether you understand the integer promotion rules
in C-an area that I find is very poorly understood by many developers.
Anyway, the answer is that this outputs "6." The reason for this is
that expressions involving signed and unsigned types have all operands
promoted to unsigned types. Thus ý20 becomes a very large positive
integer and the expression evaluates to greater than 6. This is a very
important point in embedded systems where unsigned data types should
be used frequently (see Reference 2). If you get this one wrong, you
are perilously close to not getting the job.
-------------
Jan 2 '08 #8
dspfun said:
On 2 Jan, 19:07, dspfun <dsp...@hotmail.comwrote:
>Hi!

Are suffixes allowed on expressions?

For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL

It should be:
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365) UL
The result of the above calculation will be out by 86400 seconds this year.

--
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
Jan 2 '08 #9
dspfun wrote:
What about question 12, isn't it implementation specific since the
representation of the basic types are not precisely defined by the
language?
This has nothing to do with the representation of the basic types, it
depends only upon the usual arithmetic conversions. While the results
of those conversions vary from implementation to implementation, the
particular values chose for a and b below are guaranteed to produce
the same final results on all conforming implementations of C.
---------------
12. What does the following code output and why?

void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b 6) ? puts("6") : puts("<= 6");
}

Answer:
This question tests whether you understand the integer promotion rules
in C-an area that I find is very poorly understood by many developers.
Anyway, the answer is that this outputs "6." The reason for this is
that expressions involving signed and unsigned types have all operands
promoted to unsigned types. ...
Note that this is not the correct rule in C99, though I think it's a
correct statement of the C90 rule. In C99, the signed operand is
converted to the type of the unsigned operand only if the rank of the
unsigned type is greater than or equal to the rank of the signed type.
In this case, that happens to be true.
... Thus �20 becomes a very large positive
integer and the expression evaluates to greater than 6. ...
Specifically, (a+b) has a value of UINT_MAX-13. The value of that sum
depends upon the implementation, since UINT_MAX depends upon the
implementation. However, since UINT_MAX must be at least 65535, that
value is guaranteed to be at least 65522, and therefore greater than
6, and the routine is guaranteed to pass "6" to puts().
Jan 2 '08 #10
Richard Heathfield wrote:
dspfun said:
On 2 Jan, 19:07, dspfun <dsp...@hotmail.comwrote:
Hi!

Are suffixes allowed on expressions?

For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL
It should be:
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365) UL

The result of the above calculation will be out by 86400 seconds this year.
On the originally referenced web site, the relevant question specified
that leap years are to be ignored. The macro name should have
reflected that fact, though I'm not sure of the best way to do so.
SECONDS_PER_NON_LEAP_YEAR?

Jan 2 '08 #11
On 2 Jan, 22:29, jameskuy...@verizon.net wrote:
dspfun wrote:
What about question 12, isn't it implementation specific since the
representation of the basic types are not precisely defined by the
language?

This has nothing to do with the representation of the basic types, it
depends only upon the usual arithmetic conversions. While the results
of those conversions vary from implementation to implementation, the
particular values chose for a and b below are guaranteed to produce
the same final results on all conforming implementations of C.


---------------
12. What does the following code output and why?
void foo(void)
{
Â* unsigned int a = 6;
Â* int b = -20;
Â* Â* (a+b 6) ? puts("6") : Â*puts("<= 6");
}
Answer:
This question tests whether you understand the integer promotion rules
in C-an area that I find is very poorly understood by many developers.
Anyway, the answer is that this outputs "6." The reason for this is
that expressions involving signed and unsigned types have all operands
promoted to unsigned types. ...

Note that this is not the correct rule in C99, though I think it's a
correct statement of the C90 rule. In C99, the signed operand is
converted to the type of the unsigned operand only if the rank of the
unsigned type is greater than or equal to the rank of the signed type.
In this case, that happens to be true.
... Thus �20 becomes a very large positive
integer and the expression evaluates to greater than 6. ...

Specifically, (a+b) has a value of UINT_MAX-13. The value of that sum
depends upon the implementation, since UINT_MAX depends upon the
implementation. However, since UINT_MAX must be at least 65535, that
value is guaranteed to be at least 65522, and therefore greater than
6, and the routine is guaranteed to pass "6" to puts().- Dölj citerad text -

- Visa citerad text -
Ok, thank you for the explanation! I believe it is the following in
C99 that specifies this (that the result of a+b will be UINT_MAX + 1
-20 + 6 = UINT_MAX-13):

2
Otherwise, if the new type is unsigned, the value is converted by
repeatedly adding or
subtracting one more than the maximum value that can be represented in
the new type
until the value is in the range of the new type.49)
Jan 2 '08 #12
ja*********@verizon.net wrote:
>
.... snip ...
>
On the originally referenced web site, the relevant question
specified that leap years are to be ignored. The macro name
should have reflected that fact, though I'm not sure of the
best way to do so. SECONDS_PER_NON_LEAP_YEAR?
Too long. Try SECS_PER_SQUAT_YR. :-)

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee, Frohe Weihnachten
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com

Jan 2 '08 #13
CBFalconer <cb********@yahoo.comwrites:
ja*********@verizon.net wrote:
>>
... snip ...
>>
On the originally referenced web site, the relevant question
specified that leap years are to be ignored. The macro name
should have reflected that fact, though I'm not sure of the
best way to do so. SECONDS_PER_NON_LEAP_YEAR?

Too long. Try SECS_PER_SQUAT_YR. :-)
The term for a non-leap year is "common year".

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 2 '08 #14
Keith Thompson wrote:
dspfun <ds****@hotmail.comwrites:
>Are suffixes allowed on expressions?

No (unless the expression happens to be an integer constant).
The suffix is *part* of the constant. They form one token.
You can't have e.g. `12 UL`.
--
Army1987 (Replace "NOSPAM" with "email")
Jan 3 '08 #15
CBFalconer wrote:
Ben Pfaff wrote:
>dspfun <ds****@hotmail.comwrites:
>>Are suffixes allowed on expressions?
No. The suffixes that you are talking about are allowed only on
integer and floating-point constants.
>>For example, is the following allowed:

#define SECONDS_PER_YEAR (60 * 60 * 365) UL
No. To get the apparently intended effect, you can write
#define SECONDS_PER_YEAR (60UL * 60 * 365)
or
#define SECONDS_PER_YEAR (unsigned long int) (60 * 60 * 365)

The second will only work if the expression (60 * 60 * 365) is
within the range of an int. This is doubtful if running on a 16
bit system.
And SECONDS_PER_YEAR really is equal to (60 * 60 * 24 * 365).
^^^^

--
+----------------------------------------------------------------+
| Charles and Francis Richmond richmond at plano dot net |
+----------------------------------------------------------------+
Jan 3 '08 #16
How about question 7, is it correct (referring to the test in the link
at the top of the thread)? :

int const * a const;

The declaration above doesn't compile using gcc.
Jan 3 '08 #17
dspfun wrote:
How about question 7, is it correct (referring to the test in the link
at the top of the thread)? :

int const * a const;

The declaration above doesn't compile using gcc.
'const' is a type-qualifier, and therefore a declaration-specifier.
'a' is parsed as a direct-declarator, and therefore as a declarator,
and therefore as an init-declarator-list. 6.7p1 requires that
declarations-specifiers preceed the init-declarator-list, so this is
an incorrect declaration.
Jan 3 '08 #18
On 3 Jan, 21:18, jameskuy...@verizon.net wrote:
dspfun wrote:
How about question 7, is it correct (referring to the test in the link
at the top of the thread)? :
int const * a const;
The declaration above doesn't compile using gcc.

'const' is a type-qualifier, and therefore a declaration-specifier.
'a' is parsed as a direct-declarator, and therefore as a declarator,
and therefore as an init-declarator-list. 6.7p1 requires that
declarations-specifiers preceed the init-declarator-list, so this is
an incorrect declaration.
Thanks for a great answer!

How did you do the mapping type-qualifier -declaration-specifier and
direct-declarator -declarator -init-declarator-list ?

I found something more suspicuous in the anser to question 2:

"Knowledge of the ternary conditional operator. This operator exists
in C because it allows the compiler to produce more optimal code than
an if-then-else sequence. "

Is this really true?
Jan 3 '08 #19


dspfun wrote:
On 3 Jan, 21:18, jameskuy...@verizon.net wrote:
dspfun wrote:
How about question 7, is it correct (referring to the test in the link
at the top of the thread)? :
int const * a const;
The declaration above doesn't compile using gcc.
'const' is a type-qualifier, and therefore a declaration-specifier.
'a' is parsed as a direct-declarator, and therefore as a declarator,
and therefore as an init-declarator-list. 6.7p1 requires that
declarations-specifiers preceed the init-declarator-list, so this is
an incorrect declaration.

Thanks for a great answer!

How did you do the mapping type-qualifier -declaration-specifier and
This is just a matter of reading and correctly interpreting the
productions listed in section 6.7p1.
direct-declarator -declarator -init-declarator-list ?
I left out init-declarator, between the last two items there. See
sections 6.7.5p1 and 6.7p1.
I found something more suspicuous in the anser to question 2:

"Knowledge of the ternary conditional operator. This operator exists
in C because it allows the compiler to produce more optimal code than
an if-then-else sequence. "

Is this really true?
I sincerely doubt that any modern compiler produces different code
depending upon whether if-then-else or ?: is used, and I'm quite sure
that any such minor efficiencies have nothing to do with the reason
why it exists. The ?: operator is syntactic sugar, which makes certain
construct much simpler to write. It's not necessary, but it is
occasionally convenient, and convenience should not be underrated as a
feature of a computer programming language.
Jan 3 '08 #20
dspfun <ds****@hotmail.comwrites:
How about question 7, is it correct (referring to the test in the link
at the top of the thread)? :

int const * a const;
This is probably a typo for:
int const *const a;
although I would write such a declaration as, equivalently:
const int *const a;
--
"If I've told you once, I've told you LLONG_MAX times not to
exaggerate."
--Jack Klein
Jan 3 '08 #21
In article <71**********************************@5g2000hsg.go oglegroups.com>,
dspfun <ds****@hotmail.comwrote:
>Could you give a pointer to where in the standard it says that an
integer (constant) can be typecasted to a pointer and the result is
implementation dependent?
C89 3.3.4 Cast Operators

An abitrary integer may be converted to a pointer. The result
is implementation-defined. [45]
{footnote} [45] The mapping functions for converting a pointer to
an integer or an integer to a pointer are intended to be
consistent with the addressing structure of the execution
environment.

--
"Any sufficiently advanced bug is indistinguishable from a feature."
-- Rich Kulawiec
Jan 3 '08 #22
On 4 Jan, 00:41, rober...@ibd.nrc-cnrc.gc.ca (Walter Roberson) wrote:
In article <7146c56f-be16-4c06-9a59-1a142d154...@5g2000hsg.googlegroups.com>,

dspfun *<dsp...@hotmail.comwrote:
Could you give a pointer to where in the standard it says that an
integer (constant) can be typecasted to a pointer and the result is
implementation dependent?

C89 3.3.4 Cast Operators

* An abitrary integer may be converted to a pointer. The result
* is implementation-defined. [45]

* {footnote} [45] The mapping functions for converting a pointer to
* an integer or an integer to a pointer are intended to be
* consistent with the addressing structure of the execution
* environment.

--
* *"Any sufficiently advanced bug is indistinguishable from a feature."
* *-- Rich Kulawiec
Thank you, is the same valid for C99?
Jan 3 '08 #23
dspfun <ds****@hotmail.comwrites:
A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;
It's *extremely* obscure why one would give an rvalue a const
type.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Jan 4 '08 #24
dspfun wrote:
>
.... snip ...
>
Could you give a pointer to where in the standard it says that an
integer (constant) can be typecasted to a pointer and the result
is implementation dependent?
You can answer this sort of question more easily yourself, with a
text version of the C standard and grep. grep is available
everywhere. For the text version I suggest N869_txt.bz2, which is
a bzip2 compressed version of N869, and is available at:

<http://cbfalconer.home.att.net/download/>

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Jan 4 '08 #25
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>dspfun wrote:
>>>
... snip ...
>>>
Could you give a pointer to where in the standard it says that an
integer (constant) can be typecasted to a pointer and the result
is implementation dependent?

You can answer this sort of question more easily yourself, with a
text version of the C standard and grep. grep is available
everywhere. For the text version I suggest N869_txt.bz2, which is
a bzip2 compressed version of N869, and is available at:

<http://cbfalconer.home.att.net/download/>

n1256.pdf, available at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>,
is more current. It's PDF rather than plain text, which may or may
not be a problem.

I'm not convinced that a simple grep would be useful in this case.
For example, the word "typecast" appears nowhere in the standard.
What would you grep for?
For example, I just entered:

grep -n cast \stds\n869.txt | less

and got a set of roughly 60 lines. This took all of 2 seconds. It
shouldn't take much to hide that output and just save the line
numbers, which can then be used to illuminate all the areas of
interest.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Jan 4 '08 #26
CBFalconer wrote:
Keith Thompson wrote:
>CBFalconer <cb********@yahoo.comwrites:

I'm not convinced that a simple grep would be useful in this case.
For example, the word "typecast" appears nowhere in the standard.
What would you grep for?

For example, I just entered:

grep -n cast \stds\n869.txt | less

and got a set of roughly 60 lines.
Yeah, but the OP is under the mistaken impression that "typecasting" has
something to do with C, rather than with Hollywood. :-(

It would probably have been useful to have advised him that the word he
was searching for was 'convert'.
--
Mark McIntyre

CLC FAQ <http://c-faq.com/>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
Jan 4 '08 #27
dspfun wrote:
A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;
The most obscure thing is what the `const` is for. A cast doesn't yield a
lvalue, so it's irrelevant whether it's const. Do you usually end the body
of main with `return (const int)0;`?

--
Army1987 (Replace "NOSPAM" with "email")
Jan 4 '08 #28
On 4 Jan, 01:46, Ben Pfaff <b...@cs.stanford.eduwrote:
dspfun <dsp...@hotmail.comwrites:
A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;

It's *extremely* obscure why one would give an rvalue a const
type.
Can you explain what you mean?

Isn't 0xaa55 the rvalue, 0xaa55 is an integer constant, what is the
obscure thing about that?
Jan 4 '08 #29
dspfun <ds****@hotmail.comwrites:
On 4 Jan, 01:46, Ben Pfaff <b...@cs.stanford.eduwrote:
>dspfun <dsp...@hotmail.comwrites:
A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;

It's *extremely* obscure why one would give an rvalue a const
type.

Can you explain what you mean?
"const" is attached to a type to make objects of that type
non-modifiable. But the result of a cast is never modifiable,
because it is not an lvalue. So the "const" keyword here is
useless.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,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;}}}
Jan 5 '08 #30
On 5 Jan, 06:25, Ben Pfaff <b...@cs.stanford.eduwrote:
dspfun <dsp...@hotmail.comwrites:
On 4 Jan, 01:46, Ben Pfaff <b...@cs.stanford.eduwrote:
dspfun <dsp...@hotmail.comwrites:
A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;
It's *extremely* obscure why one would give an rvalue a const
type.
Can you explain what you mean?

"const" is attached to a type to make objects of that type
non-modifiable. *But the result of a cast is never modifiable,
because it is not an lvalue. *So the "const" keyword here is
useless.
If const in the above expression statement is useless, is it also
implementation specific? Does the standard specify it to be useless
(explicitly or implicitly)?

One could imagine a cast like this:

const int * p;
p = (const int *)(0x67a9);

Then the const qualifier is not useless in the cast?
Jan 5 '08 #31
On Sat, 05 Jan 2008 08:02:31 -0800, dspfun wrote:
>dspfun <dsp...@hotmail.comwrites:
A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;

If const in the above expression statement is useless, is it also
implementation specific? Does the standard specify it to be useless
(explicitly or implicitly)?
Yes, the standard requires it to be useless:
"The properties associated with qualified types are meaningful only for
expressions that are lvalues."
One could imagine a cast like this:

const int * p;
p = (const int *)(0x67a9);

Then the const qualifier is not useless in the cast?
In that cast, the target type is an unqualified pointer. It happens to be
a pointer to a const-qualified int, but that is not relevant to the
discussion.
Jan 5 '08 #32
On 5 Jan, 17:36, Harald van D©¦k <true...@gmail.comwrote:
On Sat, 05 Jan 2008 08:02:31 -0800, dspfun wrote:
dspfun <dsp...@hotmail.comwrites:
A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;
If const in the above expression statement is useless, is it also
implementation specific? Does the standard specify it to be useless
(explicitly or implicitly)?

Yes, the standard requires it to be useless:
"The properties associated with qualified types are meaningful only for
expressionsthat are lvalues."
One could imagine a cast like this:
const int * p;
p = (const int *)(0x67a9);
Then the const qualifier is not useless in the cast?

In that cast, the target type is an unqualified pointer. It happens to be
a pointer to a const-qualified int, but that is not relevant to the
discussion.
So, are the following two pointers identical? :

const int * p1;
int * p2;

p1 can be modified to any value, but whichever object p1 addresses can
not be modified (using *p1). It seems as if the const type qualifier
information "follows" p1?

Jan 5 '08 #33
On Sat, 05 Jan 2008 10:59:18 -0800, dspfun wrote:
So, are the following two pointers identical? :

const int * p1;
int * p2;
No.
p1 can be modified to any value, but whichever object p1 addresses can
not be modified (using *p1). It seems as if the const type qualifier
information "follows" p1?
Indeed. *p1 is an lvalue of type const int, and for lvalues, type
qualifiers do matter.
Jan 5 '08 #34
On 5 Jan, 22:57, Harald van D©¦k <true...@gmail.comwrote:
On Sat, 05 Jan 2008 10:59:18 -0800, dspfun wrote:
So, are the following two pointers identical? :
const int * p1;
int * p2;

No.
p1 can be modified to any value, but whichever object p1 addresses can
not be modified (using *p1). It seems as if the const type qualifier
information "follows" p1?

Indeed. *p1 is an lvalue of type const int, and for lvalues, type
qualifiers do matter.
So, in the above, is p1 a qualified pointer, and p2 an unqualified
pointer?
Jan 5 '08 #35
On Sat, 05 Jan 2008 14:56:27 -0800, dspfun wrote:
>On Sat, 05 Jan 2008 10:59:18 -0800, dspfun wrote:
const int * p1;
int * p2;

So, in the above, is p1 a qualified pointer, and p2 an unqualified
pointer?
No. I already stated in my first message in this subthread that const int
* is an unqualified pointer to a const-qualified int. The const does not
apply to the pointer itself.

const int *p;
p = 0;

If that's valid, p is not const-qualified. That's valid.
Jan 5 '08 #36
On 6 Jan, 00:04, Harald van D©¦k <true...@gmail.comwrote:
On Sat, 05 Jan 2008 14:56:27 -0800, dspfun wrote:
On Sat, 05 Jan 2008 10:59:18 -0800, dspfun wrote:
const int * p1;
int * p2;
So, in the above, is p1 a qualified pointer, and p2 an unqualified
pointer?

No. I already stated in my first message in this subthread that const int
* is an unqualified pointer to a const-qualified int. The const does not
apply to the pointer itself.

const int *p;
p = 0;

If that's valid, p is not const-qualified. That's valid.
I guess the source of my confusion could be exemplified by the
following:

const int *p1;
int *p2;
p1 = (int *)(0x67a9);
p2 = (int *)(0x67a9);

p1 points to an int which is not modifiable while p2 points to an int
which is modifiable. But they both point to the same int.

Thanks for your time and help!!
Jan 5 '08 #37
dspfun wrote:
I guess the source of my confusion could be exemplified by the
following:

const int *p1;
int *p2;
p1 = (int *)(0x67a9);
p2 = (int *)(0x67a9);

p1 points to an int which is not modifiable while p2 points to an int
which is modifiable. But they both point to the same int.
They both point to the same /memory location/, yes.

But thats not a problem - think of it as similar to file modes. The
'const' qualifier is like opening a readonly file handle. An application
can open two handles on a file, one readonly and the other read/write.
--
Mark McIntyre

CLC FAQ <http://c-faq.com/>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
Jan 6 '08 #38
On 6 Jan, 00:57, Mark McIntyre <markmcint...@spamcop.netwrote:
dspfun wrote:
I guess the source of my confusion could be exemplified by the
following:
const int *p1;
int *p2;
p1 = (int *)(0x67a9);
p2 = (int *)(0x67a9);
p1 points to an int which is not modifiable while p2 points to an int
which is modifiable. But they both point to the same int.

They both point to the same /memory location/, yes.

But thats not a problem - think of it as similar to file modes. The
'const' qualifier is like opening a readonly file handle. An application
can open two handles on a file, one readonly and the other read/write.
Since p1 is defined as a pointer to a const int, I feel the cast of
0x67a9 should have been to a pointer which points to a const int.
But the cast of 0x67a9 is to a pointer which points to an int, and not
to a const int.
So to me it seems as if the "type" of p1 is slightly different from
the "type" of "(int *) 0x6a70".

Thanks again!
Jan 6 '08 #39
dspfun <ds****@hotmail.comwrites:
On 6 Jan, 00:57, Mark McIntyre <markmcint...@spamcop.netwrote:
>dspfun wrote:
I guess the source of my confusion could be exemplified by the
following:
const int *p1;
int *p2;
p1 = (int *)(0x67a9);
p2 = (int *)(0x67a9);
p1 points to an int which is not modifiable while p2 points to an int
which is modifiable. But they both point to the same int.

They both point to the same /memory location/, yes.

But thats not a problem - think of it as similar to file modes. The
'const' qualifier is like opening a readonly file handle. An application
can open two handles on a file, one readonly and the other read/write.

Since p1 is defined as a pointer to a const int, I feel the cast of
0x67a9 should have been to a pointer which points to a const int.
But the cast of 0x67a9 is to a pointer which points to an int, and not
to a const int.
So to me it seems as if the "type" of p1 is slightly different from
the "type" of "(int *) 0x6a70".
Yes, the types are different. One is 'const int *' the other is 'int
*'. They ('p1' and '(int *)(0x67a9)') are both pointers but to
differently qualified versions of the same type ('int').

Assignment (and also parameter passing) allows qualifiers to be added
to the "pointed to" type. There is a passage in the standard that
specifically states this permission. The reverse is not allowed:

p2 = p1;

after the code you quote is a constraint violation.

--
Ben.
Jan 6 '08 #40
dspfun wrote:
Since p1 is defined as a pointer to a const int, I feel the cast of
0x67a9 should have been to a pointer which points to a const int.
But the cast of 0x67a9 is to a pointer which points to an int, and not
to a const int.
So to me it seems as if the "type" of p1 is slightly different from
the "type" of "(int *) 0x6a70".
Well, you lied to the compiler... if you want a const int*, tell it
thats what you have !

Also - the assignment adds the constness. RTFS to determine the precise
para that allows this.

--
Mark McIntyre

CLC FAQ <http://c-faq.com/>
CLC readme: <http://www.ungerhu.com/jxh/clc.welcome.txt>
Jan 6 '08 #41
dspfun wrote:
On 4 Jan, 01:46, Ben Pfaff <b...@cs.stanford.eduwrote:
>dspfun <dsp...@hotmail.comwrites:
>>A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;
It's *extremely* obscure why one would give an rvalue a const
type.

Can you explain what you mean?

Isn't 0xaa55 the rvalue, 0xaa55 is an integer constant, what is the
obscure thing about that?
There is no connection of any kind between the 'const' in the cast
expression and the fact that 0xaa55 is a constant expression. Whatever
connection you think exists reflects a misunderstanding on your part.

In a pointer declaration, a qualifier such as 'const' that appears
before the '*' qualifies the values that are pointed at. When the
'const' occurs after the '*', it applies to the pointer value itself,
not the pointed-at value.

when the 'const' qualifier applies to an lvalue, it disqualifies the
lvalue from being modifiable. If the operand of an increment or
decrement expression, or the left operand of an assignment is not a
modifiable lvalue, it is a constraint violation. This is the main
purpose of declaring things to be 'const'. It is already a constraint
violation for (int *)(0x67a9) to be in any of those situations, because
it isn't an lvalue, so making it (int * const)(0x67a9) doesn't change
anything. The 'const' is completely pointless in that position.

Using (int const*)(0x67a9) would change things, because in that case
'const' would apply to the pointed-at value, rather than the pointer
value. The effect of using that declaration would be to make the
assignment above a constraint violation.
Jan 6 '08 #42

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: p.kosina | last post by:
Its just for my convienience: When saving new file in IDLE I HAVE to always manually add suffix .py, otherwise it is saved without ANY suffix. Can it be set somewhere? Thank you Pavel
12
by: Iain Downie | last post by:
Dear list, we are getting a few folk trying to register for our birdwatching surveys with emails of the form: aname@phonecoop.coop, in other words with a 4 character ending (other examples are...
1
by: Endif | last post by:
I am tring to execute the following SQL statements through the Iseries Navigator for DB2/V8.2, But i come up with an error saying recursion is not allowed in common table expression. This is a...
3
by: Green | last post by:
Hi, I have a question that when i surf the internet, i found out that using ..aspx suffix means using asp.net, using .jsp means using javaserver page, etc. But some don't have any suffix. For...
9
by: Hamish M | last post by:
Hi I am interested in opinions on this topic. I have heard that a suffix is not a good solution and type casts are much better for example. ...
5
by: Casey Hawthorne | last post by:
Since there was talk of if-then-else not being allowed in lambda expressions, the following is from "Dive into Python" The and-or conditional expression trick from page 41 of "Dive into Python"...
0
by: Lamy | last post by:
I am trying to set a culture in my skin file, I had used the following code in my skin file: <asp:Label ID="UserNameLabel" runat="server" Text='<%$ Resources: CreateNew, Label1UserName %>'...
3
by: Ahmedhussain | last post by:
I am writing this query but didnt understand why isnt it working... Its giving me the error : INSERT INTO (, , , , , , , , , , , , , , , , , , , , ) VALUES ((select (.User_Id) as UserID...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.