program error

S

SAHIL MAHLA

#include <stdio.h>

void main(void)
{

char* p ="sahil";
printf("%c,%c,%c,%c",*p,*(++p),*(p++),*p);

}

result-h,h,s,h

it should be - s,a,a,h

Could someone explain the result.
============================================
one more situation:

#include <stdio.h>

void main(void)
{

char p[] ="sahil"; <<<< Change in the declaration
printf("%c,%c,%c,%c",*p,*(++p),*(p++),*p); <<<<Line 7

}


Result-In function 'main':
Line 7: error: invalid lvalue in increment
Line 7: error: invalid lvalue in increment


Plz explain
 
S

Siri Cruz

SAHIL MAHLA said:
#include <stdio.h>

void main(void)
{

char* p ="sahil";
printf("%c,%c,%c,%c",*p,*(++p),*(p++),*p);

}

result-h,h,s,h

it should be - s,a,a,h

Doctor! Doctor! It hurts when I do this!

Then don't that any more.
 
K

Kaz Kylheku

#include <stdio.h>

void main(void)
^^^^^^^^^^^^^^^^

This way of declaring the main function doesn't conform to ISO C, which
specifies the behavior only for these two portable forms.

int main(void)
int main(int, char **);

Implementations can support additional forms of the startup function.
(Did you read in your toolchain documentation that void main(void)
is supported? Even if so, there isn't a good reason to write
that way.)
{

char* p ="sahil";
printf("%c,%c,%c,%c",*p,*(++p),*(p++),*p);

Here, a function is called with five arguments:

printf(arg1, arg2, arg3, arg4, arg5);

These argument values are obtained, prior to the function call, by evaluating
five argument expressions:

"%c,%c,%c,%c" -> arg1
*p -> arg2
*(++p) -> arg3
*(p++) -> arg3
*p -> arg4

(Actually, six expressions are evaluated in an unspecified order:
the printf identifier is also an expression: a function designator).

Now here is the kicker. The ISO C standard says that the order
of evaluation of these expressions is "unspecified".

In other words, evaluation does not necessarily go in the order
arg1, arg2, arg3 ... It could be in any order, including, possibly,
interleaved orders.
}

result-h,h,s,h

it should be - s,a,a,h

That's what the behavior would be with a compiler that generates code which
evaluates function arguments strictly left to right (and completely so, to the
point of settling all the side effects of one expression before moving on to
the next one: in other words, imposing a "sequence point".)

However, there is no such requirement.

The following function call to f can invoke the functions a, b and c in any of
the six possible orders:

f(a(), b(), c());

other than that, it is well-defined, because function calls are sequenced in C:
the execution of function calls cannot overlap. A sequence point occurs
before a function is called and when it returns.

In your case, the behavior is undefined because you have side effects
in your expressions (incrementing the pointer p).

In C, if an object is modified twice without a sequence point in between,
it is undefined behavior.

Somewhat confusingly, the C comma operator does impose a sequence point, and
strict left to right evaluation. So this kind of thing is well-defined:

char *q = (p++, p++, p++);

The comma which separates function argument expressions, however, does not
impose a sequence point or ordering, so the following type of thing is not well-defined:

f(p++, p++, p++);

Not well-defined means that the C standard doesn't provide a requirement
as to what the behavior should be; it is entirely in the hands of the
implementation.
one more situation:

#include <stdio.h>

void main(void)
{

char p[] ="sahil"; <<<< Change in the declaration

p is now the name of an array, and not a pointer.
printf("%c,%c,%c,%c",*p,*(++p),*(p++),*p); <<<<Line 7

Here, you're trying to increment an array.

The standard calls this situation a "constraint violation", which requires a
diagnostic.

The ++ operator can only be applied to lvalues which are integers,
floating-pointers numbers or pointers.

Maybe in some future version of standard C, ++p will mean "increment every
element of the array p", or something else.
 
S

SAHIL MAHLA

#include <stdio.h>

void main(void)

^^^^^^^^^^^^^^^^



This way of declaring the main function doesn't conform to ISO C, which

specifies the behavior only for these two portable forms.



int main(void)

int main(int, char **);



Implementations can support additional forms of the startup function.

(Did you read in your toolchain documentation that void main(void)

is supported? Even if so, there isn't a good reason to write

that way.)


{

char* p ="sahil";
printf("%c,%c,%c,%c",*p,*(++p),*(p++),*p);



Here, a function is called with five arguments:



printf(arg1, arg2, arg3, arg4, arg5);



These argument values are obtained, prior to the function call, by evaluating

five argument expressions:



"%c,%c,%c,%c" -> arg1

*p -> arg2

*(++p) -> arg3

*(p++) -> arg3

*p -> arg4



(Actually, six expressions are evaluated in an unspecified order:

the printf identifier is also an expression: a function designator).



Now here is the kicker. The ISO C standard says that the order

of evaluation of these expressions is "unspecified".



In other words, evaluation does not necessarily go in the order

arg1, arg2, arg3 ... It could be in any order, including, possibly,

interleaved orders.


}



it should be - s,a,a,h



That's what the behavior would be with a compiler that generates code which

evaluates function arguments strictly left to right (and completely so, to the

point of settling all the side effects of one expression before moving on to

the next one: in other words, imposing a "sequence point".)



However, there is no such requirement.



The following function call to f can invoke the functions a, b and c in any of

the six possible orders:



f(a(), b(), c());



other than that, it is well-defined, because function calls are sequenced in C:

the execution of function calls cannot overlap. A sequence point occurs

before a function is called and when it returns.



In your case, the behavior is undefined because you have side effects

in your expressions (incrementing the pointer p).



In C, if an object is modified twice without a sequence point in between,

it is undefined behavior.



Somewhat confusingly, the C comma operator does impose a sequence point, and

strict left to right evaluation. So this kind of thing is well-defined:



char *q = (p++, p++, p++);



The comma which separates function argument expressions, however, does not

impose a sequence point or ordering, so the following type of thing is not well-defined:



f(p++, p++, p++);



Not well-defined means that the C standard doesn't provide a requirement

as to what the behavior should be; it is entirely in the hands of the

implementation.


one more situation:
#include <stdio.h>
void main(void)

char p[] ="sahil"; <<<< Change in the declaration



p is now the name of an array, and not a pointer.


printf("%c,%c,%c,%c",*p,*(++p),*(p++),*p); <<<<Line 7



Here, you're trying to increment an array.



The standard calls this situation a "constraint violation", which requires a

diagnostic.



The ++ operator can only be applied to lvalues which are integers,

floating-pointers numbers or pointers.



Maybe in some future version of standard C, ++p will mean "increment every

element of the array p", or something else.




Hi Kaz,

Thank you so much for such an explainatory answer for my query.

Which book do you reccomend for going through all the advance concepts in C.
 

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

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top