2

I learning these concepts, please help me why the following code is throwing a segmentation fault. My intention in this code is to print capital letter D and move to next address. Please explain me. thank u.

main()
{
    char *ptr="C programming";
    printf(" %c \n",++*ptr);    
}
Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
t.purna Chander
  • 123
  • 2
  • 8

4 Answers4

7

Reason for your error

You are trying to modify a string literal, which is a non-modifiable object. That's why you get a segmentation fault.

Even if you simply call ptr[0]++, it will be a segmentation fault.

Solution

One solution is to change the declaration to:

char ptr[] = "C programming"

Then you can modify the char array.

They look similar? Yes, the string literal is still non-modifiable, but you have declared an array with its own space, which will be initialized by the string literal, and the array is stored in the stack, and thus modifiable.

Example

Here is a full code example:

#include <stdio.h>

int test() {
    char str[]="C programming";
    char *ptr = str;

    while(*ptr != '\0') {
        // print original char,
        printf("%c \n", *(ptr++));

        // print original char plus 1, but don't change array,
        // printf("%c \n", (*(ptr++))+1);

        // modify char of array to plus 1 first, then print,
        // printf("%c \n", ++(*(ptr++)));
    }

    return 0;
}

int main(int argc, char * argv[]) {
    test();
    return 0;
}

Tip: you should only enable one of the printf() lines at the same time, due to ++ operator.

More tips

Note that we declared a ptr and a str, because we can't use ++ operation on an array (you can't change the address of an array), thus ++str will get a compile error, while ++ptr won't.


@Update - About memory

(To answer your comment)

  • A string literal is usually stored in a read-only area of a process; refer to C string literals: Where do they go?
  • A char array, if declared inside a method, then it's allocated on the stack, thus you can modify it; when you initialize a char array from a string literal, there are actually 2 copies of the same value: 1 is read-only; 1 is modifiable; the char array is initialized from the read-only copy.
  • A char pointer it stores a single address; the pointer itself is allocated on stack in this case, and you can modify it.

You might also want to know more about pointer or address or array or Linux process memory layout_ or data sections of a C program; try searching on Google, or refer to books like The C Programming Language, 2nd Edn and The Linux Programming Interface — though this is a question about C rather than Linux. There's also The Definitive C Book Guide and List on Stack Overflow.

Community
  • 1
  • 1
Eric
  • 22,183
  • 20
  • 145
  • 196
  • This is close to right answer, but not quite. The poster said he wanted it to print `D` ie increment the value prior to printing it. – Kurt Stutsman Feb 17 '16 at 05:21
  • Thank u. It s has become a bit confusing . can u explain me bit more about these ,, ptr [ ] " and ,, *ptr '' . – t.purna Chander Feb 17 '16 at 05:23
  • @t.purnaChander I updated the answer a little, but you need use google or read books to get a better understand of such concepts, I guess. – Eric Feb 17 '16 at 05:35
  • @KurtStutsman Yeah, I see, then need change the printf line to `printf("%c \n", (*(ptr++))+1);` – Eric Feb 17 '16 at 05:50
3

This will print D then increment the pointer to the next char.

#include <stdio.h>

main()
{
    char *ptr="C programming";
    printf(" %c \n",(*ptr++) + 1);    
}

You cannot increment the character value in place in memory as it is a character literal and as such most probably stored in the data section of your binary executable. it's read only and any attempts to alter it will lead to undefined behaviour (segfault probably ~100% of the time).

You should make a habit of declaring such literals const. Indeed c++ will pull you up on this if it has any extra level of warnings enabled.

The above code works because it is not altering the memory, it is simply adding 1 to the value for the purpose of passing to printf.

Another option is to use array syntax instead of pointer syntax, you are declaring the string to be on the stack and so it is writeable.

To do this the syntax is

char ptr[]="C programming";

You can think of a pointer just pointing anywhere, you give the compiler an option to put it wherever it likes, so it sticks it in read only memory. When you use array syntax is has to be right there, where you declare it.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
  • ya.. thank u for that. I got it. But y there was a segmentation fault with my code, as I m trying to increase the ascii value if C , which will give D, and then move to next address location. Will you please explain me that ? – t.purna Chander Feb 17 '16 at 05:12
  • @Eric Wang has already explained that. I wont try to repeat his answer. – Paul Rooney Feb 17 '16 at 05:14
  • Can u suggest some material to get some clarity about these concepts. thank u. – t.purna Chander Feb 17 '16 at 05:17
  • @t.purnaChander there are some extremely in depth, advanced books like [this] (http://linker.iecc.com/). Depending on your experience level you may or may not find it useful. Other than that you can study the basics of assembler or there may be articles on the net. I'm not certain entry level c books would cover this. – Paul Rooney Feb 17 '16 at 23:14
0

Assuming you are trying to increment the ascii value of C by one and print that and move the character pointed to forward, you want to use *ptr++ + 1.

codemaker
  • 1,682
  • 1
  • 11
  • 13
0

why the following code is throwing a segmentation fault

++*ptr means *ptr = *ptr + 1

in C, string literal is a non-modifiable object. You are trying to dereference ptr and set value for the address that ptr points to.

Van Tr
  • 5,889
  • 2
  • 20
  • 44