Deep understanding of C pointer and variable, taking address of a string literal [closed]

Solution 1:

The behavior of this is defined by the C standard except for the fact that write is a Unix routine outside of the C standard.

"a" is a string literal. That is, it is source code that denotes a string. For this string literal, an array of two char is created, one with the code for the character “a” and the second with zero.

In &"a", the array is the operand of unary &, so the common automatic conversion of an array to a pointer to its first element is not performed. Then & takes the address of the array.

So &"a" produces a pointer to where the array starts in memory, with the type char (*)[2], that is, a pointer to an array of two char.

write is declared as ssize_t write(int fildes, const void *buf, size_t nbyte);, so its second parameter has type const void *. In calling this routine, the char (*)[2] will be automatically converted to const void *.

Any pointer to object type can be converted to void *, and qualifiers can be added, so this conversion is allowed. Further, it is allowed as an implicit conversion; no cast is required. (The rules for converting function arguments to parameter types refer to the rules for assignment in C 2018 6.5.16.1, and these allow implicit conversion to void * and addition of qualifiers.)

write is specified to write bytes of the object it is passed. Its documentation does not say that object has to be any particular type. Commonly, we pass it the address of the first byte of an array of bytes, but we can pass it the address of any object we want to write. For example, if I wanted to write the raw binary data of some structure to disk, and I would read it back later in the same C implementation, then passing write the address of the structure would be fine. Passing it &"a", with one byte to be written, has defined behavior.