I have a char pointer
with string literal like this char *d="abc";
and I am incrementing it like
*(d+1)
I get something like b
if I do printf("%c",*(d+1))
But when I have these lines
char *c={'a','b','c'}
printf("%c\n",*(c+1)); /// CAUSES SegFault
Above line throwing exception. when I try to do backtrace and print *(c+1) with gdb it says $1 = 0x61 <error: Cannot access memory at address 0x61>
So my question is why this does not work compare to when I assign string literal to char pointer
same happens when I assign array of int
to int pointer
and increment it this way
Major thanks to @nielsen for pointing this out, it all became clear after their comment.
First of all, let's try a similar program that won't segfault:
For me, this outputs:
0x61
. That should ring a bell, it's the same address that GDB gave.More important, however, are the warnings I am getting:
initialization makes pointer from integer without a cast [-Wint-conversion]
was already pointed out in the comments. However, with another warning, this becomes clear:Basically, this doesn't do what you think it does. At all. the
{}
is a "scalar" initializer. From https://en.cppreference.com/w/c/language/type, here's an excerpt:A pointer happens to be a scalar type because it can only hold 1 value, which is an address. So the compiler will only use
'a'
to initializec
sincec
can only hold 1 value, and ignores everything else (because again, scalar). What's the ASCII value of'a'
in hex? 61, the exact same number as the address GDB pointed out. Hopefully, you get what's going on now:When the compiler sees
char *c = {'a', 'b', 'c'};
, it treats the aggregate initializer as a scalar initializer becausec
is a scalar variable, so only takes'a'
and tells you off for putting 2 extra characters.'a'
, anint
literal, is implicitly converted tochar *
and it becomes an address. The compiler also warns you about this.You try to print
*(c + 1)
, but since that is an invalid address/you're not allowed to touch that address, a segfault occurs.What I think you actually want to do is treat
c
as an array. To do this, you can either changec
's type into an array:Or keep
c
as achar *
and use a compound literal:However,
char *c = {'a', 'b', 'c'};
is not valid C as a brace-enclosed scalar initializer is only allowed to hold 1 expression. Vlad's answer gives the specific quote from the standard that proves this. Compiling this code with-pedantic-errors
will replace all the warnings mentioned here with errors.