Suffix allowed on expressions?

J

jameskuyper

dspfun said:
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.
 
B

Ben Pfaff

dspfun said:
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;
 
D

dspfun

This is just a matter of reading and correctly interpreting the
productions listed in section 6.7p1.

Ok, if I've understood things correctly in the C standard, this is how
the productions listed in section 6.7p1 should be read (with respect
to the above declaration the above declaration):

6.3.2.1p2: An identifier is a sequence of nondigit characters
(including the underscore _, the lowercase and uppercase Latin
letters, and other characters) and digits, which designates one or
more entities as described in 6.2.1.

Hence, "a" is an identifier.


6.7p6: The declarators contain the identifiers (if any) being
declared.

6.7.5p2:Each declarator declares one identifier, and asserts that when
an operand of the same form as the declarator appears in an
expression, it designates a function or object with the scope, storage
duration, and type indicated by the declaration specifiers.

Hence, "* a" is a declarator.


6.7p1:
init-declarator:
declarator
declarator = initializer

Hence, "* a" is also an init-declarator.

6.7p1:
init-declarator-list:
init-declarator
init-declarator-list , init-declarator

Hence, "a *" is also the init-declarator-list.

--------------------------------------------------

6.7.3p1:
type-qualifier:
const
restrict
volatile

Hence, "const" is a type-qualifier.

6.7p1:
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt

Hence, "const" is a declaration-specifier.

--------------------------------------------------

6.7p1:
declaration:
declaration-specifiers init-declarator-listopt ;

Hence, "const" has to preceed "* a"
 
D

dspfun

I have another doubt, isn't question 10 implementation specific? I.e.
there is no way in standard (portable) C to access a specific memory
locataion by providing a numerical address as described in the
question and answer below? There could for example be virtual memory
addresses on top of hardware addresses.

Here is the question:
-------------------------------------
Accessing fixed memory locations
10. Embedded systems are often characterized by requiring the
programmer to access a specific memory location. On a certain project
it is required to set an integer variable at the absolute address
0x67a9 to the value 0xaa55. The compiler is a pure ANSI compiler.
Write code to accomplish this task.

This problem tests whether you know that it is legal to typecast an
integer to a pointer in order to access an absolute location. The
exact syntax varies depending upon one's style. However, I would
typically be looking for something like this:

int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;

A more obscure approach is:
*(int * const)(0x67a9) = 0xaa55;

Even if your taste runs more to the second solution, I suggest the
first solution when you are in an interview situation.

----------------------------
 
W

Walter Roberson

I have another doubt, isn't question 10 implementation specific? I.e.
there is no way in standard (portable) C to access a specific memory
locataion by providing a numerical address as described in the
question and answer below?

C does permit an integer to be typecast to a pointer, but it says that
the result is implementation dependant, even putting aside alignment
issues. The resulting pointer might not be usable for any accesses no
matter what value was cast; the resulting pointer might be usable for
an access to an address that doesn't look anything like the integer;
the resulting pointer might be usable for an access into the program's
virtual memory rather than to an absolute address; the resulting
pointer might be usable for an access to an absolute address; the
ability to use the pointer to access an absolute address might depend
upon the privileges the program has been granted; the ability to use
the pointer to access an absolute address might depend upon the exact
absolute address and whether the system has been configured to allow
user programs to access that specific address.

So, just as you say, the result is indeed system specific.
 
D

dspfun

C does permit an integer to be typecast to a pointer, but it says that
the result is implementation dependant, even putting aside alignment
issues.

Ok, thank you for your answer!

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

Walter Roberson

dspfun said:
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.
 
D

dspfun

dspfun   said:
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.

Thank you, is the same valid for C99?
 
J

jameskuyper

dspfun said:
On 4 Jan, 00:41, (e-mail address removed)-cnrc.gc.ca (Walter Roberson) wrote: ...
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.
...
Thank you, is the same valid for C99?

Essentially. Section 6.3.2.3 says:

"An integer may be converted to any pointer type. Except as previously
specified, the
result is implementation-defined, might not be properly aligned, and
might not point to an
entity of the referenced type."

The footnote is the same.
 
K

Keith Thompson

Keith Thompson said:
There's a contact address in the article; I'll send him pointers to
your article and my followup.

With the author's permission, I'm posting his response to my e-mail.
I've rearranged the text to put his response after mine, and I've
added "|| " before my message and "| " before his response.

|| Hello. Somebody just posted a pointer to your article "A 'C'
|| Test: The 0x10 Best Questions for Would-be Embedded Programmers",
|| <http://www.embedded.com/2000/0005/0005feat2.htm> to the comp.lang.c
|| Usenet newsgroup, pointing out a serious error in the first question.
|| I've posted a followup. You can read the orginal post at
||
|| http://groups.google.com/group/comp.lang.c/msg/131a36cd616fa566
||
|| and my followup at
||
|| http://groups.google.com/group/comp.lang.c/msg/7029524f1567fe2f
||
|| There have been several other responses in the thread; persuading
|| Google Groups to show the tree of responses is left as an exercise.
||
|| (My first attempt to send you this message bounced because I had the
|| wrong e-mail address. I think the article is fairly old; the URL
|| implies that it's from the year 2000 -- though "curl --head" says
|| the "0005feat2.htm" was last modified Tue, Jan 27 2099 23:59:59 GMT.
|| Somebody might want to look into the settings on your web server.)
|
| Hi Keith:
|
| I took a look at your post. The UL outside the brackets was a typesetting
| error that wasn't caught on the proof read. Incidentally, a far more
| interesting thing to note is whether the UL actually buys you anything. I
| think it does, but I've had others that disagree with me.
|
| Regarding Q8 - I think you missed my point. In my experience less than 10%
| of C programmers know what volatile is, let alone all its subtleties. Given
| that this was a C *test*, the objective was more to test than to teach. In
| short if an embedded programmer doesn't know what volatile is, or has a hazy
| knowledge, then they are useless.
|
| In question 14. Regarding the needless cast to the result of malloc(). I
| personally am very cautious with implicit casts. Thus it's my style to
| always cast the result of malloc and other such functions. Having said that,
| I can't remember the last time I used malloc() since heap fragmentation is
| not normally something I can tolerate.
|
| Sticking with question 14, you are correct that I was wrong about the
| results of malloc(0). I erroneously thought that malloc(0) always returned a
| valid pointer. Having said that, the main point of the question was to
| determine which of the two "camps" you fall in to.
|
| Camp "1": The programmer is king. I'm smarter than the compiler, so if I
| want to do something like call malloc(0) then I expect a valid pointer.
|
| Camp "2": I'm human and make stupid mistakes. I'd really like the compiler
| to remind me when I do something stupid, or at least suspicious.
|
| BTW, if you genuinely knew that the results of malloc(0) was implementation
| dependent, then I suspect that you are a compiler writer, or you spend more
| time reading compiler manuals than I do, since I think you'd agree it's a
| pretty obscure point.
|
| I'm sorry that my attitude / tone for Q15 offended you. The article was
| supposed to be light hearted, while at the same time making some good
| points. As to your claim that the solution to Q15 is something every C
| programmer should know - I agree. However, I think you'll find that >95%
| can't answer this question correctly. If you're in an organization with many
| programmers, I'd be interested to see how many of them can answer the
| question correctly. (BTW, the folks that hang out on the comp.lang.c Usenet
| newsgroup probably aren't representative of the programming population.)
|
| Incidentally, what I have found with Q15 is that the better candidates
| instinctively know that the typedef is the better solution - but without
| being able to quite articulate why.
|
| Thanks for writing.
 
C

CBFalconer

dspfun said:
.... 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/>
 
K

Keith Thompson

CBFalconer said:
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?

I just found the relevant section in n1256.pdf by traversing the
table of context, which is easy to do in a decent PDF reader:

6 Language
6.3 Conversions
6.3.2 Other operands
6.3.2.3 Pointers
Paragraph 5:
An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity
of the referenced type, and might be a trap representation.

(The last line of the paragraph has a change bar, which means it
changed post-C99.)
 
C

CBFalconer

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

Mark McIntyre

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

Army1987

dspfun said:
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;`?
 
D

dspfun

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?
 
B

Ben Pfaff

dspfun said:
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.
 
D

dspfun

"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?
 
H

Harald van Dijk

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.
 

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,769
Messages
2,569,582
Members
45,060
Latest member
BuyKetozenseACV

Latest Threads

Top