-3

Can you find what is wrong with the following code?

int main(){
    char *p="hai friends",*p1;
    p1=p;
    while(*p!='\0') ++*p++;
    printf("%s %s",p,p1);
}

I expected it will print space followed by a string!

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
pcc
  • 81
  • 1
  • 1
  • 8

3 Answers3

9

The expression ++*p++; is equivalent to;

++*p; 
p++;

++*p; means

*p = *p + 1;

Because postfix ++ has higher precedence than the dereference operator *, it's applied on *p.

And p points to a constant string literal. In the above operation you are trying to "write on read only memory" — that is illegal — hence error.

Suggestions:

First — declare your an array that can be modified, you can't change string literals.
declare (read comments):

char string_array[] ="hai friends"; // notice `[]` in this declaration
                                    // that makes `string_array` array 

// to keep save original string do:
char p1[20]; // sufficient length  // notice here `p1` is not pointer.
strcpy(p1, string_array) ;

char *p = string_array;

Now you can modify pointer p and string_array[] array content.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
4

Although the answer by Grijesh Chauhan is correct in saying that:

++*p++;

and

++*p;
p++;

have the same effect, the compiler does not interpret the first expression as if it was written like the second. The parenthesized version of the first expression is:

++(*(p++));

This means that logically — though the compiler can resequence the details as long as the result is the same — the post-increment of p occurs before the result is dereferenced, and the pre-increment operates on the data pointed at by the original value of p. Let's go through that step by step:

  1. p++ — returns the original value of p and increments p to point to the next character.
  2. *(p++) — dereferences the original value of p.
  3. ++(*(p++) — increments the object pointed at by the original value of p and returns the incremented value of that object.

Thus, given this code (which avoids modifying string literals — that is undefined behaviour):

    #include <stdio.h>

    int main(void)
    {
        char array[] = "ayqm";
        char *p = array;
        char c;
        c = ++*p++;
        printf("%c\n", c);
        printf("%s\n", array);    // Print the string
        c = ++*p++;               // Repeat the process
        printf("%c\n", c);
        printf("%s\n", array);
        return 0;
    }

The output is:

b
byqm
z
bzqm

Nothing in this answer should be construed as encouraging the use of expressions as complex as ++*p++. It is not easy C to understand or maintain, and therefore it is not good C. However, it is legitimate C. If the variable p points to initialized modifiable memory, the behaviour of ++*p++ is completely defined.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

Here is a way to use ++*p++:

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) {
  char *p = "My test string", p1[15];

  strncpy(p1, p, 14);
  p1[14] = 0;
  p = p1;

  while (*p != 0) {
    printf("%c", ++*p++);
  }
}

Note that p1 is an array of memory (usually) allocated on the stack, whereas p is (usually) a pointer to read only memory, which the above code moves to point to p1 instead of the (usually) read only location where the string resides. Some operating systems and/or compilers will exhibit other behavior, but this is one of the protection mechanisms built into modern OSs to prevent certain classes of viruses.

abiessu
  • 1,907
  • 1
  • 18
  • 16
  • 1
    so,when we assign a character pointer , a string,the string is written in memory and a pointer is returned and stored,and the memory area is read-only,but when we declare a char array, a modifiable memory area is allocated..right??thanx, it ws great and nice help1 – pcc Jul 23 '13 at 19:29
  • 2
    The declarations and `strncpy()` are a contorted way of writing: `char p1[] = "My test string"; char *p = p1;`. Also, `p1` is not 'dynamically allocated'; that term is reserved for memory allocated using `malloc()` et al. It is modifiable memory; it is automatically allocated (storage class `auto`); it is not dynamically allocated. – Jonathan Leffler Aug 31 '13 at 17:33
  • 2
    Interestingly, the C standard does not contain the word 'dynamically', so my comment should be taken as meaning "most people talking about memory allocation expect dynamically allocated memory (in C) to be allocated via `malloc()` et al". If `p1` is dynamically allocated, so is `p` (and `argc` and `argv`). – Jonathan Leffler Aug 31 '13 at 17:54
  • @jonathanleffler thank you for pointing that out, I had forgotten how to use the terminology correctly. I have corrected my post. – abiessu Aug 31 '13 at 20:40