Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > C Test Incorrectly Uses printf() - Please Confirm

Reply
Thread Tools

C Test Incorrectly Uses printf() - Please Confirm

 
 
Shao Miller
Guest
Posts: n/a
 
      08-08-2010
Shao Miller wrote:
> I suppose the only well-behaved way to do it is:
>
> int i = 1, j;
> j = i;
> i = i + j;
>
> Is that right?

Or:

int i = 1;
i = i * 2;

(Of course.)
 
Reply With Quote
 
 
 
 
Shao Miller
Guest
Posts: n/a
 
      08-08-2010
Willem wrote:
> Shao Miller wrote:
> ) As in, the second argument has a definite value at least by the time of
> ) the function call. So does the third argument have a value. It doesn't
> ) matter whether the third argument's value is 6 or 7, because the format
> ) string doesn't use it. Thus '2' is printed.
>
> It's undefined behaviour. Anything can happen.
> '2' is not *guaranteed*.
>
> I agree, it's extremely unlikely to be anything else.
> Probably no system exists where it would not print 2.
> But pedantically speaking, the result *is* undefined.
>
> But in some theoretical machine, it could fail.
> (For example, the instructions for reading in a+5 and writing in a++
> could be parallelized into the same slot, and the simultaneous read
> and write could cause some kind of signal to be raised.)

What makes it undefined behaviour, if you please?

Is it also undefined behaviour for:

int i = 1;
i = i + i;

?
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      08-08-2010
On 8/8/2010 4:47 PM, Shao Miller wrote:
> Willem wrote:
>> Shao Miller wrote:
>> ) As in, the second argument has a definite value at least by the time
>> of ) the function call. So does the third argument have a value. It
>> doesn't ) matter whether the third argument's value is 6 or 7, because
>> the format ) string doesn't use it. Thus '2' is printed.
>>
>> It's undefined behaviour. Anything can happen.
>> '2' is not *guaranteed*.
>>
>> I agree, it's extremely unlikely to be anything else.
>> Probably no system exists where it would not print 2.
>> But pedantically speaking, the result *is* undefined.
>>
>> But in some theoretical machine, it could fail.
>> (For example, the instructions for reading in a+5 and writing in a++
>> could be parallelized into the same slot, and the simultaneous read
>> and write could cause some kind of signal to be raised.)

> What makes it undefined behaviour, if you please?


`++a, a+5' with no sequence point to separate them. 6.5p2:

"Between the previous and next sequence point an object
shall have its stored value modified at most once by the
evaluation of an expression. Furthermore, the prior value
shall be read only to determine the value to be stored."

.... with special attention to the second sentence. `++a' reads the
value once to determine the value stored, and `a+5' reads the value
for a different purpose. U.B.

> Is it also undefined behaviour for:
>
> int i = 1;
> i = i + i;


No. The Standard says "shall be read," not "shall be read
exactly once."

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      08-08-2010
Eric Sosman wrote:
> On 8/8/2010 2:55 PM, Martin O'Brien wrote:
>> I took an online C test a few months ago. I actually thought the test
>> was better than some I've taken, but one question in particular I
>> think has the wrong answer. The question is this:
>>
>> What is printed:
>>
>> int a = 1;
>> printf("%d", ++a, a + 5);
>>
>> ... ... ...

>
> Ponder this one:
>
> printf ("%d\n", ++a, strlen(NULL));
>
> The fact that the printf() will not use its third parameter does not
> mean that the third argument's undefined behavior is forgiven.

I'm not sure I'd agree to pondering this example for similarity to the
first. There are two additional sequence points here; one before the
call to 'strlen' and one immediate before 'strlen' returns. Thus there
is more opportunity for undefined behaviour than in the original. Would
you agree?

5.1.2.3,p2 (of 'n1256.pdf'):

"...At certain specified points in the execution sequence called
sequence points, all side effects of previous evaluations shall be
complete and no side effects of subsequent evaluations shall have taken
place."
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      08-08-2010
On 8/8/2010 5:17 PM, Shao Miller wrote:
> Eric Sosman wrote:
>> On 8/8/2010 2:55 PM, Martin O'Brien wrote:
>>> I took an online C test a few months ago. I actually thought the test
>>> was better than some I've taken, but one question in particular I
>>> think has the wrong answer. The question is this:
>>>
>>> What is printed:
>>>
>>> int a = 1;
>>> printf("%d", ++a, a + 5);
>>>
>>> ... ... ...

>>
>> Ponder this one:
>>
>> printf ("%d\n", ++a, strlen(NULL));
>>
>> The fact that the printf() will not use its third parameter does not
>> mean that the third argument's undefined behavior is forgiven.

> I'm not sure I'd agree to pondering this example for similarity to the
> first. There are two additional sequence points here; one before the
> call to 'strlen' and one immediate before 'strlen' returns. Thus there
> is more opportunity for undefined behaviour than in the original. Would
> you agree?


(Shrug.) If that worries you, consider

printf ("%d\n", ++a, *(char*)NULL);

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      08-08-2010
Eric Sosman wrote:
> On 8/8/2010 4:47 PM, Shao Miller wrote:
>> Willem wrote:
>>> Shao Miller wrote:
>>> ) As in, the second argument has a definite value at least by the time
>>> of ) the function call. So does the third argument have a value. It
>>> doesn't ) matter whether the third argument's value is 6 or 7, because
>>> the format ) string doesn't use it. Thus '2' is printed.
>>>
>>> It's undefined behaviour. Anything can happen.
>>> '2' is not *guaranteed*.
>>>
>>> I agree, it's extremely unlikely to be anything else.
>>> Probably no system exists where it would not print 2.
>>> But pedantically speaking, the result *is* undefined.
>>>
>>> But in some theoretical machine, it could fail.
>>> (For example, the instructions for reading in a+5 and writing in a++
>>> could be parallelized into the same slot, and the simultaneous read
>>> and write could cause some kind of signal to be raised.)

>> What makes it undefined behaviour, if you please?

>
> `++a, a+5' with no sequence point to separate them. 6.5p2:
>
> "Between the previous and next sequence point an object
> shall have its stored value modified at most once by the
> evaluation of an expression. Furthermore, the prior value
> shall be read only to determine the value to be stored."
>
> ... with special attention to the second sentence. `++a' reads the
> value once to determine the value stored, and `a+5' reads the value
> for a different purpose. U.B.

Thanks, Eric.

>> Is it also undefined behaviour for:
>>
>> int i = 1;
>> i = i + i;

>
> No. The Standard says "shall be read," not "shall be read
> exactly once."
>

I think I understand. So in:

int i = 1, j;
i = j = i + i * 9 + 3;

we are likewise protected because we can conclude that sooner or later
within some expression, we are modifying the stored value of 'i'. Is
that right?
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      08-08-2010
On Sun, 8 Aug 2010 11:55:26 -0700 (PDT), "Martin O'Brien"
<(E-Mail Removed)> wrote:

>I took an online C test a few months ago. I actually thought the test
>was better than some I've taken, but one question in particular I
>think has the wrong answer. The question is this:
>
> What is printed:
>
> int a = 1;
> printf("%d", ++a, a + 5);
>
> a. 1
> b. 2
> c. 7
> d. undefined
>
>I selected d. This is the explanation given as to why b is the correct
>answer.
>
> The first expression in the parameter list following the format
>string is paired with the first (and only) conversion specification.
>The increment is a prefix so the result of the operation is the a + 1.
>Since there are more items in the value list than there are conversion
>specifications, the extra value is not shown.
>
>I believe the correct answer is d because according to K&R2 (and by
>implication the Standard) the order in which function arguments are
>evaluated is not defined; in fact, K&R2's example, in Section 2.12,
>shows the variable n being used twice in the same printf call (albeit
>with the correct number of conversion specifications).
>
>Am I correct that d is the correct answer?


I think so, due to violating 6.5-2.

There is a sequence point prior to the start of the printf statement.
The next sequence pint is when printf is called. Between the two, the
arguments are evaluated. As a result of evaluating the second
argument, the value stored in object a is modified, we just don't know
exactly when. Evaluating the third argument reads the value of object
a for a purpose other than determining what the new value should be.

The fact that the third argument is never used probably eliminates the
practical impact of the undefined behavior. (I wonder if there are
any systems other than the DS9000 which would fail to do the
expected.) But that does not change the fact that a shall constraint
has been violated.

--
Remove del for email
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      08-08-2010
Barry Schwarz wrote:
> On Sun, 8 Aug 2010 11:55:26 -0700 (PDT), "Martin O'Brien"
> <(E-Mail Removed)> wrote:
>
>> I took an online C test a few months ago. I actually thought the test
>> was better than some I've taken, but one question in particular I
>> think has the wrong answer. The question is this:
>>
>> What is printed:
>>
>> int a = 1;
>> printf("%d", ++a, a + 5);
>>
>> a. 1
>> b. 2
>> c. 7
>> d. undefined
>>
>> I selected d. This is the explanation given as to why b is the correct
>> answer.
>>
>> The first expression in the parameter list following the format
>> string is paired with the first (and only) conversion specification.
>> The increment is a prefix so the result of the operation is the a + 1.
>> Since there are more items in the value list than there are conversion
>> specifications, the extra value is not shown.
>>
>> I believe the correct answer is d because according to K&R2 (and by
>> implication the Standard) the order in which function arguments are
>> evaluated is not defined; in fact, K&R2's example, in Section 2.12,
>> shows the variable n being used twice in the same printf call (albeit
>> with the correct number of conversion specifications).
>>
>> Am I correct that d is the correct answer?

>
> I think so, due to violating 6.5-2.

I disagree.
>
> There is a sequence point prior to the start of the printf statement.
> The next sequence pint is when printf is called. Between the two, the
> arguments are evaluated.

Agreed.

> As a result of evaluating the second
> argument, the value stored in object a is modified, we just don't know
> exactly when.

I disagree. 5.1.2.3,p2:

"...At certain specified points in the execution sequence called
sequence points, all side effects of previous evaluations shall be
complete and no side effects of subsequent evaluations shall have taken
place."

The object designated by 'a' has its stored value modified not before
the sequence point just before calling the function. The side effects
are effectively coalesced at that point in time, by this definition.

> Evaluating the third argument reads the value of object
> a for a purpose other than determining what the new value should be.
>

The argument list in a function call is a comma-separated list of
expressions to be evaluated, not a single expression (the syntax of
6.5.2,p1 and the semantics of 6.5.2.2,p3). 6.5,p2 states "an
expression" rather than "an expression or a comma-separated list of
expressions".

> The fact that the third argument is never used probably eliminates the
> practical impact of the undefined behavior.

I do not agree that there is no undefined behaviour. I believe that the
correct answer is (b).

> (I wonder if there are
> any systems other than the DS9000 which would fail to do the
> expected.) But that does not change the fact that a shall constraint
> has been violated.
>

The value of 'a' is stable between its initializing declaration and the
instant before 'printf' is called. No single expression attempts to
modify the value and read the value for some other purpose. Would you
agree?
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      08-08-2010
Shao Miller wrote:
> I do not agree that there is no undefined behaviour. I believe that the
> correct answer is (b).

Please forgive the typo. That should have been typed as:

I do not agree that there is undefined behaviour. I believe that the
correct answer is (b).
 
Reply With Quote
 
Shao Miller
Guest
Posts: n/a
 
      08-08-2010
pete wrote:
> Shao Miller wrote:
>> Ersek, Laszlo wrote:

>
>>> Furthermore,
>>> the prior value shall be read only to determine the value
>>> to be stored.

>
>> Whoa. It never occurred to me that:
>>
>> int i = 1;
>> i = i + i;
>>
>> could yield undefined behaviour

>
> That's good that it didn't occur to you.
>
> The part that Ersek, Laszlo wrote which I didn't snip,
> applies to that situation.
>
> Here's the footnote that goes with it.
>
> N869
> 60)This paragraph renders undefined statement expressions
> such as
> i = ++i + 1;
> a[i++] = i;
> while allowing
> i = i + 1;
> a[i] = i;
>

Yes, a good (albeit, non-normative) footnote to think about.

i = ++i + 1;

At the sequence point, we have two modification accesses pending for 'i'
at the same time. Oops! The value of 'i' is guaranteed intact until
that sequence point.

a[i++] = i;

Is defined to be equivalent to:

(*((a) + (i++))) = i;

At the sequence point, we have a modification access pending for the
object designated by '(*((a) + (i++)))' and we have a modification
access pending for 'i' at the same time. Both of these accesses are
uses of the value of 'i' in a single expression. Since only one of the
modification accesses is for 'i', this could be considered as the prior
value being read for more than just the purpose of determining the value
to be stored in 'i'.

i = i + 1;

At the sequence point, we have a modification access pending for 'i' and
this is a use of the prior value of 'i'. Eric has suggested that more
than one read of 'i' is allowed, which would satisfy 'i = i + i;'.

a[i] = i;

Is defined to be equivalent to:

(*((a) + (i))) = i;

At the sequence point, we have a modification access pending for the
object designated by '(*((a) + (i)))'. There is no modification access
pending for 'i', so we can read the value of 'i' as many times as we like.

So how about here?:

int i = 1, j;
i = j = i + i + 1;

At the sequence point just before the second semi-colon, we have a
modification access pending for 'i' and a modification access pending
for 'j'. Is the value of 'i' read for more than one purpose here?

Thanks, pete.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C Test Incorrectly Uses printf() - Please Confirm Martin C Programming 4 08-10-2010 05:25 PM
Confirm my Performance Test Against Java? Ben Christensen Ruby 39 09-03-2009 05:20 AM
Please: ITemplate propery being saved incorrectly -- Attributes usage incorrect? S.Sigal ASP .Net Building Controls 0 08-14-2004 02:07 PM
Please: ITemplate propery being saved incorrectly -- Attributes usage incorrect? S.Sigal ASP .Net Web Controls 0 08-14-2004 02:04 PM
test test test test test test test Computer Support 2 07-02-2003 06:02 PM



Advertisments