James Kuyper
5/2/2011 12:24:00 PM
On 05/02/2011 07:38 AM, arnuld wrote:
> I have this program which is causing confusion to me. I am told that last
> printf() of main() will always print "Second", not "First". I think line:
>
> x = myAlloc(x);
>
> is UB. My colleague is disagreeing on this while I was saying that its UB
> because there is no sequence point here. It is just like using this line:
>
> i = i++;
No, it's not. 6.5p2 contains two separate "shalls" that apply between
consecutive sequence points. "i=i++" violates the first one, against
modifying the value of an object twice. Your example modifies the value
of x only once. I presume, therefore, that you're actually worried about
the second one, against reading the value for any purpose other than to
determine what the new value is.
> But he says that sequence point will not affect the pointers and hence
> this is perfectly valid ANSI C program. I am confused on this:
There is no special exemption of pointers from the rules involving
multiple modifications with no intervening sequence points. "x=x++"
would be just as thoroughly undefined as "i = i++". It's just that
there's a whole lot more relevant sequence points involved in the
evaluation of "x = myAlloc(x)" than you're taking into consideration.
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> enum { SIZE_LIMIT = 10 };
>
> char* myAlloc(char* c);
>
> int main(void)
> {
> char* x = malloc(SIZE_LIMIT * sizeof *x);
> if(NULL == x)
> {
> printf("Out of Memory\n");
> return EXIT_FAILURE;
> }
>
> strcpy(x, "First");
> printf("x = %s\n", x);
> x = myAlloc(x);
There's a sequence point separating evaluation of 'x' as an argument to
myAlloc() from the call to myAlloc() (6.5.2.2p10).
> printf("x = %s\n", x);
>
> return 0;
> }
>
>
> char* myAlloc(char* c)
> {
> c = malloc(SIZE_LIMIT * sizeof *c);
There's a sequence point separating the multiplication from the call to
malloc(), another just before malloc() returns (7.1.4p3), a third at the
end of the full expression (6.8p4).
> if(NULL == c)
There's a sequence point at the end of the full expression.
> {
> printf("Out of Memory\n");
> return NULL;
> }
> else
> {
> strcpy(c, "Second");
There's a sequence point separating the evaluation of the arguments from
the call to strcpy(), a second just before strcpy() returns, and a third
at the end of the full expression.
> }
>
> return c;
There's a sequence point at the end of the full expression.
> }
I count a total of 9 sequence points separating the reading of the value
of x from its modification. One is all that's needed to avoid violating
6.5p2.
--
James Kuyper