I have the following code,

main()
{
char *p="abc";
int x;
x=++*p++;
printf("%d",x);
}

My question is, when I try to do x=++*p++, the program crashes. If my associativity rules are right, first the address pointed to by p should be incremented by the postfix (p++) and then the value (*p) should be applied, and thereafter the prefix operator should be used. Why did it not give a compiler error saying lvalue required?

As, when the compiler first does *p++, it is retrieving the value of the address pointing to by p. (As per my understanding).

Recommended Answers

All 30 Replies

The first ++ tried to modify what p points to.
Since p points to a string constant, your program dies because it tried to modify something in read-only memory.

try this:

char q[16];
char *p = &q;
strcpy(q,"abc");

.

> char *p = &q;
Did you try it?

&q has a different type to q, so any good compiler would complain about incompatible pointer assignments.

commented: keeping me honest :) +12

&q has a different type to q, so any good compiler would complain about incompatible pointer assignments

yes, you're right.

even though it works for this trivial example, not casting it properly is a bad habit to get into.

the correct way to initialize it is:

char q[16];
char *p = [b](char *)[/b]&q;
strcpy(q,"abc");
commented: Nope, you're still wrong -7

yes, you're right.

even though it works for this trivial example, not casting it properly is a bad habit to get into.

the correct way to initialize it is:

char q[16];
char *p = [b](char *)[/b]&q;
strcpy(q,"abc");

So you get the wrong type, then cast it to the right type and rely on the starting address being the same for both to make it all work out. Why not use the right type from the start and not need to cast at all?

/* better */
char q[16];
char *p = q;
strcpy(q,"abc");

Array names become pointers when used as a value. But you don't need to do any of that because q can be passed to strcpy directly, or even initialized to a string constant:

/* easier */
char q[16];
strcpy(q, "abc");
/* even easier */
char q[16] = "abc";

I can't figure out why you have a magic number of 16, but there's probably a reason. Otherwise you don't need any size if you initialize to a string constant:

/* easiest */
char q[] = "abc";

You can't get much shorter than that for a modifiable string. ;)

commented: Quite so +36
commented: super cool post +2

A little addition on:

Array names become pointers

Yes, an array name is a constant pointer to the first element of that array.

A little addition on:

Array names become pointers

Yes, an array name is a constant pointer to the first element of that array.

An array name is the name of an array object, nothing more, nothing less. When used as a value, it is converted to a pointer to the first element. When used as an object, there is no conversion. It's a subtle difference, but important when you get to object usage like char a[] = "string" , &a , and sizeof(a) . All of those work the right way because the array is not converted to a pointer.

commented: Yes you're right :) +15

:$

The real problem over here.Why the code fails.
=================================

1) ++*p++; ==>> ++ (*(p++)) ==> ++ (*k) where k=p+1(note:in k address of p+1 is stored)

2) ++ (*k) means it tries to increment the value at address of k by 1 which is a falure.

3)it should be *(++k)

SOLUTION:

++*p++ will always fail.
it can be done in 2 steps

step1:*(p++); or *p++
step2:*(++p); or *++p;

#include<stdio.h>

main()
{
char *p="agcd";
int x;
printf("string:%s and address:%d\n",p,p);
p++;					//Break ----1
printf("string:%s and address:%d\n",p,p);
*p--;                                   //Break-----2
printf("string:%s and address:%d\n",p,p);
x=*++p;
printf("x is:%d and string is:%s\n",x,p);
x=*p++;
printf("x is:%d and string is:%s\n",x,p);
x=*p++;
printf("x is:%d and string is:%s\n",x,p);
printf("x is:%d and string is:%s\n",x,p);
return 0;
}

Analysis:
=========
NOte that here break 1 (p++) and break2 (*p++ ) doing the same thing.

output log:
===========
sdetlab01:/export/home/dpani/cprograms/mdump> point
string:agcd and address:2736
string:gcd and address:2737
string:agcd and address:2736
x is:103 and string is:gcd
x is:103 and string is:cd
x is:99 and string is:d
x is:99 and string is:d
sdetlab01:/export/home/dpani/cprograms/mdump>

i hope it will clear everything to solve the thread.

Thanks,
DP

> NOte that here break 1 (p++) and break2 (*p++ ) doing the same thing.
Better add someone else to the reading list....

No they're not the same, one merely increments the pointer, the other one ALSO dereferences it at some point.

The second being equivalent to someImaginaryDummyWhichGetsThrownAway = *p++; A good compiler would have warned about a discarded result.

Oh, to be pedantic, you print a pointer like this printf("string:%s and address:%p\n",p,(void*)p); The rest of your analysis is wrong as well.
There is nothing wrong per se with ++*p++, so long as p is pointing to memory which can be MODIFIED. The original error was because p was pointing to read-only memory, and has nothing to do with the syntax of the expression being faulty.

commented: Bingo. +21

Better add someone else to the reading list

this thread is a disaster. :)

you are a patient man, Salem.


.

So my program dies because I try to fiddle with the const pointer? Shouldn't the compiler be reporting that?

So my program dies because I try to fiddle with the const pointer? Shouldn't the compiler be reporting that?

No, let's revise: your pointer points to a string constant (remember it's a constant = read-only), up until here there's nothing wrong, but further in your program there's an instruction which tries to modify that string constant, because a constant may not be modified from within the program, your program dies.
But there's nothing wrong with having a pointer to a string constant in your program, you only have to make sure that you only read the data where the pointer points to, and that you don't try to modify it.
So the issue in your program was that you were trying to modify a constant value.

Shouldn't the compiler be reporting that?

How is the compiler supposed to know? All it sees is a char pointer, not a char pointer to read only memory. The compiler assumes you know what you're doing and doesn't slow down compilation with expensive checks to protect you from something like that.

If you want that kind of protection, you need to help the compiler along by using const char *p instead of char *p when pointing to something that shouldn't be modified.

Well to be pedantic again, you should have written
const char *p="abc";
then the compiler itself would have complained about the attempt to modify a constant.

Because so much existing code (prior to C89) used this construct before the idea of putting "strings" in read-only memory came along, it was generally decided that it was better to not complain about the loss of const in such pointer assignments.

If you use some other type apart from char, it should really complain about the loss of const.

commented: nailed it! +2

> NOte that here break 1 (p++) and break2 (*p++ ) doing the same thing.
Better add someone else to the reading list....

No they're not the same, one merely increments the pointer, the other one ALSO dereferences it at some point.

The second being equivalent to someImaginaryDummyWhichGetsThrownAway = *p++; A good compiler would have warned about a discarded result.

Oh, to be pedantic, you print a pointer like this printf("string:%s and address:%p\n",p,(void*)p); The rest of your analysis is wrong as well.
There is nothing wrong per se with ++*p++, so long as p is pointing to memory which can be MODIFIED. The original error was because p was pointing to read-only memory, and has nothing to do with the syntax of the expression being faulty.

Thanks Salem.

well its resides in read only memory so

why *p++ works
why *++p works

and ++*p fails??

here in the 3 rd case we are trying to increment the values present at that address.It what i can understand.

Any suggestion regarding this??

this thread is rich of information for learners like me... :)

You seem to have figured it out - what do you want me to suggest?

Hello Salem,

NO salem, i dont want to suggest you.I just want to confirm that my understanding is correct or not because i havent read that from any book i feel the thing like this.

And i cant understand your read only memory concept.
and how dat becomes a const pointer??

Thanks,
DP

using
[char *ptr = "abc"]is the same as
[const char * ptr], so the compiler's assigns memory which is only readable and not write"able". i guess that is what is meant by Read only memory as stated above :)

commented: well explained +2

using
[char *ptr = "abc"]is the same as
[const char * ptr], so the compiler's assigns memory which is only readable and not write"able". i guess that is what is meant by Read only memory as stated above :)

Dear adarshcu,
Now i got your point.thanks.
1)char *abc="xyz";
2)char abc[]="xyz";
3)char *abc;
abc="xyz"
4)char *abc;
abc=(char*)malloc(100);
strcpy(abc,xyz);

Thanks,
DP

Here 1,2 and 3 are read only and 4 is writable. ryt??

Dear adarshcu,
Now i got your point.thanks.
1)char *abc="xyz";
2)char abc[]="xyz";
3)char *abc;
abc="xyz"
4)char *abc;
abc=(char*)malloc(100);
strcpy(abc,xyz);

Thanks,
DP

Here 1,2 and 3 are read only and 4 is writable. ryt??

1) read only
2) writeable

3) wrong, you only create a pointer of type char, this can't hold a string.
BTW, if you had written it like this:

/* wrong */
char abc[5];
abc = "xyz";

/* right */
char abc[5];
strcpy(abc, "xyz");

Then it was still wrong because you have to use strcpy.
This is writeable, because this pointer is not allowed to point to constant variables within your program.
If you've a pointer, you'll first need to assign some memory to it if you want to store a string.
Note: You should take care that this pointer doesn't modify memory that doesn't belong to the program, or your program will die.

4) writeable
I assume you meant: strcpy(abc, "xyz");

3) wrong, you only create a pointer of type char, this can't hold a string.

The next line assigns the pointer to a string constant:

char *abc;
abc="xyz";

There is no problem here, and the string is read only. It is the same to initializing directly:

char *abc = "xyz";

In fact, the compiler will probably reduce both ways to the same machine code.

commented: Thanks for the correction :) +16

A short guide to const.

char a;
const char b;
char *p = &a;
const char *q = &b;
char * const r = &a;
const char * const s = &b;

Step 1, read right to left, so for example
r is a const pointer to char.

Step 2, note that const can appear in two different places.
- the const to the right of the * means the pointer itself is const, that is (*p)++ may be allowed (modifying what it points to), but p++ isn't (modifying the pointer).
Also, such pointers MUST be declared and initialised in one step. Being const, you cannot assign them later on.

- the const to the left of the * means the thing being pointed to is const, that is p++ may be allowed, but (*p)++ isn't.

In the example above, the two RED declarations allow you to modify what the pointer points to, and the two GREEN ones do NOT allow you to modify what the pointer points to.


> I just want to confirm that my understanding is correct or not
It was good.

Hi All,

Thanks Salem.Now i can get a clear picture about these things.
I appriciate Tom Gunn and tux4life for thier clear idea about pointers.

Thanks,
DP

Must read FAQ const-correctness

You can't change the value pointed by p:

char  *p="A1C";
  *(p+1)='R';

But you may change a value of p:

char  *p="A1C";
    char ar[]="PQR";

    printf("\n%d",*p);
    p++;
    printf("\n%d",*p);

    p=ar;
    printf("\n%d",*p);
    p++;
    printf("\n%d",*p);

With const keyword

char const *p="ABC";
 char ar[]="PQR";

 *p='1';   /* Can't be modified */

  p=ar;    /* Can be assigned */
 *p='R';   /* Can't be modified */

With const keyword,

char *const p="ABC";
  char ar[]="ABC";

  p=ar;     /* Can't re-assign       */
  *p='R';   /* Can't be modified  */

  char ar[]="ABC";
  char *const p=ar;
  char br[10];

   p=br;  /* Can't re-assign   */
  *p='R';  /* can be modified  */

It seems that most people other than Tom Gunn need to swing by here and have a nice long read.

http://c-faq.com/aryptr/index.html

..that is potentially the most useful page about a C topic I have ever encountered.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.