sequence point in printf's argument list? 
Author Message
 sequence point in printf's argument list?

Hello people,

I was playing with the %n conversion specifier and the `*' field with
specifier to line up some output. I thought that this should be legal,
but it segfaults on me:

#include <stdio.h>
int main(void)
        int t;
        printf("hello%n%*s", &t, 15 - t, "world\n");
        return 0;

Quote:
}

However, this works fine:

#include <stdio.h>
int main(void)
        int t;
        printf("hello%n", &t);
        printf("%*s", 15 - t, "world\n");
        return 0;

Quote:
}

I was thinking that the first one should work, since a comma is a
sequence point, but then realised that a comma in an argument list of a
function is not a comma *operator*, but merely a comma separating the
arguments, and the second piece of code above is the only workable
solution. Am I correct in this?

Stig
--
brautaset.org



Thu, 23 Sep 2004 00:55:15 GMT  
 sequence point in printf's argument list?

Quote:
> Hello people,
> I was playing with the %n conversion specifier and the `*' field with
> specifier to line up some output. I thought that this should be legal,
> but it segfaults on me:
> #include <stdio.h>
> int main(void)
>    int t;
>    printf("hello%n%*s", &t, 15 - t, "world\n");
>    return 0;
> }
> However, this works fine:
> #include <stdio.h>
> int main(void)
>    int t;
>    printf("hello%n", &t);
>    printf("%*s", 15 - t, "world\n");
>    return 0;
> }
> I was thinking that the first one should work, since a comma is a
> sequence point, but then realised that a comma in an argument list of a
> function is not a comma *operator*, but merely a comma separating the
> arguments, and the second piece of code above is the only workable
> solution. Am I correct in this?

Yes, you are correct. A comma in a function parameter list is nothing
whatsoever like the comma operator. Your C implementation is free to
process the function parameters in any order it wishes. So it might
use the "15 - t" parameter before it uses the "&t" parameter.

A separator comma can be turned into the comma operator by wrapping it
inside parantheses. For example:
printf("%d\n", 1, 2);
prints 1, but:
printf("%d\n", (1, 2));
prints 2.

--

| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste       W++ B OP+                     |
\----------------------------------------- Finland rules! ------------/
"Outside of a dog, a book is a man's best friend. Inside a dog, it's too dark
to read anyway."
   - Groucho Marx



Thu, 23 Sep 2004 01:14:09 GMT  
 sequence point in printf's argument list?


Quote:
> Hello people,

> I was playing with the %n conversion specifier and the `*' field with
> specifier to line up some output. I thought that this should be legal,
> but it segfaults on me:

> #include <stdio.h>
> int main(void)
> int t;
> printf("hello%n%*s", &t, 15 - t, "world\n");
> return 0;
> }

> However, this works fine:

> #include <stdio.h>
> int main(void)
> int t;
> printf("hello%n", &t);
> printf("%*s", 15 - t, "world\n");
> return 0;
> }

> I was thinking that the first one should work, since a comma is a
> sequence point, but then realised that a comma in an argument list of a
> function is not a comma *operator*, but merely a comma separating the
> arguments, and the second piece of code above is the only workable
> solution. Am I correct in this?

You are correct that a comma in an argument list is not the comma operator,
however, that is not what is causing the problem.  There is a sequence point
between the evaluation of the arguments, and the actual call to printf.
Hence, subexpression:
   15-t
must be evaluated before printf is called.  Hence, in your first example, it
must be based on the initial value of t (and which, since it's
uninitialized, does invoke Undefined Behavior).

--
poncho



Thu, 23 Sep 2004 01:42:26 GMT  
 sequence point in printf's argument list?


Quote:
> Hello people,

> I was playing with the %n conversion specifier and the `*' field with
> specifier to line up some output. I thought that this should be legal,
> but it segfaults on me:

> #include <stdio.h>
> int main(void)
> int t;
> printf("hello%n%*s", &t, 15 - t, "world\n");

Evaluation of uninitialized object 't' produces
undefined behavior.

Quote:
> return 0;
> }

> However, this works fine:

> #include <stdio.h>
> int main(void)
> int t;
> printf("hello%n", &t);
> printf("%*s", 15 - t, "world\n");

Evaluation of uninitialized object 't' produces
undefined behavior.

Quote:
> return 0;
> }

> I was thinking that the first one should work, since a comma is a
> sequence point,

Not in an argument list, it's not.

Quote:
>but then realised that a comma in an argument list of a
> function is not a comma *operator*, but merely a comma separating the
> arguments,

Right.

Quote:
>and the second piece of code above is the only workable
> solution.

It's not 'workable'.  It produces undefined behavior.

Quote:
>Am I correct in this?

No.

-Mike



Thu, 23 Sep 2004 03:29:32 GMT  
 sequence point in printf's argument list?

Quote:



> > Hello people,

> > I was playing with the %n conversion specifier and the `*' field with
> > specifier to line up some output. I thought that this should be legal,
> > but it segfaults on me:

> > #include <stdio.h>
> > int main(void)
> > int t;
> > printf("hello%n%*s", &t, 15 - t, "world\n");

> Evaluation of uninitialized object 't' produces
> undefined behavior.

> > return 0;
> > }

> > However, this works fine:

> > #include <stdio.h>
> > int main(void)
> > int t;
> > printf("hello%n", &t);
> > printf("%*s", 15 - t, "world\n");

> Evaluation of uninitialized object 't' produces
> undefined behavior.

You've lost me here.  I thought that, in this case, printf("hello%n",
&t) would assign the number of characters written so far to t, so t
would have a value (5, in this case), so that evaluating t would be legal.

[...]

-Peter



Thu, 23 Sep 2004 04:24:25 GMT  
 sequence point in printf's argument list?

Quote:




(snip)

Quote:
> > However, this works fine:

> > #include <stdio.h>
> > int main(void)
> > int t;
> > printf("hello%n", &t);
> > printf("%*s", 15 - t, "world\n");

> Evaluation of uninitialized object 't' produces
> undefined behavior.

It's not uninitialized. Look up the meaning of the %n conversion
specifier... (Hint, it actually stores something in the
adress provided as argument). No - I don't like it, but it is
part of the standard.

(snip)

Quote:
> >and the second piece of code above is the only workable
> > solution.

> It's not 'workable'.  It produces undefined behavior.

No it does not, at least not for that reason. It does seem
to be missing some braces and a return statement though in
the version included above ;-)

--
/Svante

http://axcrypt.sourceforge.net
Free AES Point'n'Click File Encryption for Windows 9x/ME/2K/XP



Thu, 23 Sep 2004 04:29:39 GMT  
 sequence point in printf's argument list?


Quote:



> > > Hello people,

> > > I was playing with the %n conversion specifier and the `*' field with
> > > specifier to line up some output. I thought that this should be legal,
> > > but it segfaults on me:

> > > #include <stdio.h>
> > > int main(void)
> > > int t;
> > > printf("hello%n%*s", &t, 15 - t, "world\n");

> > Evaluation of uninitialized object 't' produces
> > undefined behavior.

> > > return 0;
> > > }

> > > However, this works fine:

> > > #include <stdio.h>
> > > int main(void)
> > > int t;
> > > printf("hello%n", &t);
> > > printf("%*s", 15 - t, "world\n");

> > Evaluation of uninitialized object 't' produces
> > undefined behavior.

> You've lost me here.  I thought that, in this case, printf("hello%n",
> &t) would assign the number of characters written so far to t, so t
> would have a value (5, in this case), so that evaluating t would be legal.

Yes, you're right.  Only the first example causes
(possible) UB, depending upon the order of evaluation
of printf()'s arguments.  I overlooked the %n.  Oops.

-Mike



Thu, 23 Sep 2004 05:49:09 GMT  
 sequence point in printf's argument list?


Quote:






> > > > Hello people,

> > > > I was playing with the %n conversion specifier and the `*' field
with
> > > > specifier to line up some output. I thought that this should be
legal,
> > > > but it segfaults on me:

> > > > #include <stdio.h>
> > > > int main(void)
> > > > int t;
> > > > printf("hello%n%*s", &t, 15 - t, "world\n");

> > > Evaluation of uninitialized object 't' produces
> > > undefined behavior.

> > > > return 0;
> > > > }

> > > > However, this works fine:

> > > > #include <stdio.h>
> > > > int main(void)
> > > > int t;
> > > > printf("hello%n", &t);
> > > > printf("%*s", 15 - t, "world\n");

> > > Evaluation of uninitialized object 't' produces
> > > undefined behavior.

> > You've lost me here.  I thought that, in this case, printf("hello%n",
> > &t) would assign the number of characters written so far to t, so t
> > would have a value (5, in this case), so that evaluating t would be
legal.

> Yes, you're right.  Only the first example causes
> (possible) UB, depending upon the order of evaluation
> of printf()'s arguments.

Nope, it always causes UB, independent of the order of evaluation.  There is
a sequence point between the evaluation of 15-t and the call to printf
(which, given the %n, will write a value of t).  There is no sequence point
between the evaluation of 15-t and &t, but since evaluating &t does nothing
to initialize t, this does not matter in this case.

--
poncho



Thu, 23 Sep 2004 07:35:39 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Variable argument list (c.f. printf())

2. re#define'ing printf/variable arguments

3. replacing printf with my printf, then calling C lib's printf

4. Specifying nothing in a function's variable argument list

5. #define's with variable length argument lists?

6. variable argument lists (va_arg)--determining number of arguments

7. Assignment and sequence points

8. Sequence Points & Side Effects

9. Sequence point question (function result semantics)

10. Sequence point or not?

11. Yet another sequence point question

12. Sequence points

 

 
Powered by phpBB® Forum Software