Arnab Bhowmick
Arnab Bhowmick

Reputation: 31

Difference between printf("%c",*(*(ptr+i)+x)) and printf("%s",*(*(ptr+i)+x))

I've an array of pointer, When I'm trying this C code getting an error of segmentation fault. What I'm doing wrong here?

  char *ptr[] = {"exam","example","testexample"};
    printf("%c\n",*(*(ptr+2)+7));
    printf("%s\n",*(*(ptr+2)+7));

In output of First print statement giving the expected result

   printf("%c\n",*(*(ptr+2)+7)); 
  m

but the second one instead of giving output of

  mple

is giving

   printf("%s\n",*(*(ptr+2)+7));    Segmentation fault (core dumped)

What I'm doing wrong here?

Upvotes: 0

Views: 160

Answers (4)

The problem is the use of the expression *(*(ptr+2)+7) - it is hard to see what it does. That construct is used mostly by beginners who do not know C intimately yet. That is why C has a syntactic sugar for it: *(*(ptr+2)+7) is exactly equivalent to ptr[2][7], which is the form you should be using.

Now, ptr[2][7] clearly is a char, but %s expects a pointer to a char, the first character in a null-terminated string, so let's pass in a pointer to that character:

printf("%s\n", &ptr[2][7]);

Upvotes: 0

marcelom
marcelom

Reputation: 81

((ptr+2)+7) is a char value

So the first statement is correct since "%c" tells printf that first parameter is a char:

printf("%c\n",*(*(ptr+2)+7));

But in the second statement , "%s" tells printf that first parameter is (char *), that is a pointer to a char. That way, when program executes

printf("%s\n",*(*(ptr+2)+7));

looks at the value of ((ptr+2)+7) ( a char value, in this case 'm' ) as if it where a char pointer. That is the reason of the segmentation fault.

So the corrected secon statement would be

printf("%s\n",*(ptr+2)+7);

Hope this helps.

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

The type of the expression

*(*(ptr+2)+7)

is char. So the first call of printf is correct.

But the second call is incorrect because the format specifier %s expects an argument of the type char *. So the value of the character obtained by the expression *(*(ptr+2)+7) that is the character 'm' (that for example in ASCII has the value 100) is interpreted as an address.

In the second call just use

*(ptr+2)+7

Here is a demonstrative program

#include <stdio.h>

int main(void) 
{
    char *ptr[] = { "exam", "example", "testexample" };

    printf( "%c\n", *( *( ptr + 2 ) + 7 ) );

    printf( "%s\n", *( ptr + 2 ) + 7 );

    return 0;
}

Its output is

m
mple

Upvotes: 2

hmakholm left over Monica
hmakholm left over Monica

Reputation: 23332

Your argument *(*(ptr+2)+7) evaluates to one character with the value 'm', which (on an ASCII-based platform) is the same as the number 109.

When you do

printf("%s\n",*(*(ptr+2)+7));

this is exactly the same as

printf("%s\n",'m');

It gets compiled to machine code that loads the number 109into a register and pushes that register on the stack. It doesn't tellprintfanything about _where it found_ that'm'` -- only that one raw ASCII value gets passed to the function.

printf then tries to interpret the 109 not as a character itself but as a pointer to some characters -- because that's what you asked it to do by writing %s. This, unsurprisingly, goes horribly wrong, since 109 is not the address of anything the program is allowed to access.

If you want to print the tail end of the string, you could instead write

printf("%s\n", *(ptr+2)+7 );

where you don't apply the * operator to the pointer you want to pass.

Upvotes: 0

Related Questions