0

I am following the "C Primer Plus" and encounter the following codes:

//strptr.c -- strings are pointers
#include <stdio.h>
int main(void)
{
    printf("%s, %p, %c\n", "We", "are", *"space farers");

    return 0;
}

Run it and come by:

./a.out
We, 0x1066e4fa1, s

Reference to the *"space farers", the book explains that:

*"space farers" should produce the value to which the address points, which should be the first character of the string "space farers".

Does it mean that *"space farers" is an address?
There's no pointers declared in the head?

AbstProcDo
  • 19,953
  • 19
  • 81
  • 138

4 Answers4

3

"space farers" is a sequence of characters. C handles this by treating it as a pointer to the first character. This is why you see

char * str = "space farers";

*xx says 'return what this pointer xx points at'. For *"space farers" thats the first character of the string, ie s.

A clearer way would be

 char * str = "space farers";
 char s = *str;

this removes the strange *"...." construct;

pm100
  • 48,078
  • 23
  • 82
  • 145
  • 3
    I would say this is incorrect by omission. A string literal is an array and C _may_ handle this - _depending on context_ - by converting it to a pointer to the first element (character). See: https://godbolt.org/z/ckDEZK - if what you say in your answer was universally true, the static assertion would pass - but it fails instead. – davmac Oct 16 '18 at 15:48
  • For a rep 89 person I think we need to pitch the answer at the appropriate level – pm100 Oct 16 '18 at 16:07
  • How does the 89 begin to explain it... more so than the title of the book? – Antti Haapala -- Слава Україні Oct 16 '18 at 16:47
  • regardless I think that adding a note saying "(this is a simplification which doesn't always apply)" would make the answer more correct and not make it less useful for beginners. – davmac Oct 17 '18 at 08:02
3

"space farers" is a string literal - a string literal is an lvalue in C is of type char [n] where n is the number of characters in the literal plus one for the null terminator. In this case it is 13.

In almost all contexts an lvalue of array type decays to a pointer to the first element. Since the elements are of type char, the value after decay is of type char *.

The * dereferences the given pointer, which results to an lvalue of the element type - here of type char. This then is evaluated for its value - i.e. the value of the first character, which is integer 's' (115 if ASCII is the execution character).


TL;DR:

*"space farers" in itself is not an address, but an lvalue of type char that is the first character in the string. You can take an address of an lvalue with the & operator.


P.S. String literals, and string values are not pointers, but arrays.

3

Under most circumstances, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. The exceptions occur when the array expression is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration.

Thus, for any array

T arr[N];

the expression arr will "decay" to type "pointer to T", and the value will be the same as &arr[0].

The expression "space farers" has type "13-element array of char". Since it isn't the operand of the sizeof or unary & operators, and it isn't being used to initialize a character array in a declaration, it "decays" to an expression of type char *, and the value of the expression is the address of the first element of the array. Just as *arr is equivalent to arr[0], *"space farers" is equivalent to "space farers"[0], and gives us the value stored in the first element of the array - the character value 's'.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • so any array such as `{1, 2, 3}` is a pointer in its nature? – AbstProcDo Oct 16 '18 at 23:16
  • "space farers" is equivalent to {'s', 'p','a',...}, but *{'s','p','a',...} does not work. – AbstProcDo Oct 16 '18 at 23:37
  • 1
    @riderdragon: No, arrays are not pointers; array *expressions* are converted to pointer expressions as necessary, but array *objects* are not pointers. The brace notation only works in an initializer. – John Bode Oct 17 '18 at 00:04
0

"space farers"is of type char[]. When passed to a function (printf in this case) it decays to char* and so *"space farers" is of type char and holds 's'.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122