4

I know that in C both of these works:

char* string = "foo";
printf("string value: %s", string);

and more simply:

printf("string value: %s", "foo");

But I was asking myself why.

I know that %s identifier expects the argument to be a char*, and string actually is (and it will be the same with an array of characters, because this two datatypes are pretty the same in C)

but when I pass directly a string to printf shouldn't it be different? I mean "foo" is not a pointer anymore... Right?.

ela
  • 325
  • 2
  • 10

5 Answers5

6

The string constant "foo" has type char []. When passed to a function, the array decays to a pointer, i.e. char *. So you can pass it to a function that expects the same.

For the same reason, you can also pass a variable of this type:

char string[4] = "foo";
printf("string value: %s", string);
dbush
  • 205,898
  • 23
  • 218
  • 273
2

The "foo" is string literal. It represents an unnamed array object with static storage duration of type char[4] (that is, without const qualifier), that is passed to function by value, just as it would be with any "normal" array.

Even though the array is not const, you are not allowed to modify its values. Such modification results in undefined behavior:

char* string = "foo";
string[0] = 'b'; // wrong, this invokes UB

The array has four elements, because of trailing null character '\0', sometimes reffered as NUL character. Please don't confuse it with NULL, which is a different thing. The purpose of that character is to terminate given string literal.

The function's parameter receives pointer to char, as array object is converted into pointer to array's first element (i.e. pointer to first character in array). To be precise, not the whole pointer is passed, only the address (i.e. the value of the pointer) it holds.

Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
1

In C, all strings are null-terminating char[] so your example will interact in the same exact way.

The ISO C standard, section 7.1.1, defines a string this way:

A string is a contiguous sequence of characters terminated by and including the first null character.

chickenwingpiccolo
  • 193
  • 1
  • 3
  • 13
0

What printf() gets, is a pointer:

ISO/IEC 9899:TC3, 6.5.2.2 – 4:

An argument may be an expression of any object type. In preparing for the call to a function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument.81)

81) A parameter declared to have array or function type is adjusted to have a pointer type as described in 6.9.1.

ISO/IEC 9899:TC3, 6.9.1 – 10:

On entry to the function, the size expressions of each variably modified parameter are evaluated and the value of each argument expression is converted to the type of the corresponding parameter as if by assignment. (Array expressions and function designators as arguments were converted to pointers before the call.)

Amin Negm-Awad
  • 16,582
  • 3
  • 35
  • 50
  • Your quotes are about parameter types, not arguments. The corresponding parameter type for `printf` is `...` (ellipsis), not an array parameter and not a variably modified parameter. – M.M Jun 23 '16 at 22:12
  • 6.3.2.1/3 (C11 numbering) is the section describing conversion of array to pointer, in arguments and elsewhere – M.M Jun 23 '16 at 22:13
  • No, my first quote is about the parameter types. And my second quote is about passing arguments respecting the parameter type. – Amin Negm-Awad Jun 24 '16 at 04:15
-1

"foo", in the end, is a pointer literal pointing to a statically allocated 4-byte memory region (likely marked read-only) that is initialized with the content: 'f'. 'o', 'o', '\0'.

Thomas B Preusser
  • 1,159
  • 5
  • 10