str(hello)
or str(hello )
is the string literal "hello"
. In passing, note that the trailing space character is not included:
If, in the replacement list, a parameter is immediately preceded by a
# preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the
preprocessing token sequence for the corresponding argument. Each
occurrence of white space between the argument’s preprocessing tokens
becomes a single space character in the character string literal.
White space before the first preprocessing token and after the last
preprocessing token composing the argument is deleted.
(6.10.3.2 The # operator, C99).
In memory this is 'h'
, followed by 'e'
, ..., followed by 'o'
, followed by the null character (a byte with all bits set to 0, typically represented by '\0'
):
'h' 'e' 'l' 'l' 'o' '\0'
When you apply strcat
like that, it tries to replace '\0'
with a 'D'
'h' 'e' 'l' 'l' 'o' 'D'
then make the subsequent bytes 'a'
, 'v'
, ..., 'd'
, '\0'
:
'h' 'e' 'l' 'l' 'o' 'D' 'a' 'v' 'i' 'd' '\0'
At least two problems with this:
- bytes after the
'\0'
have probably not been allocated to you!
- it is considered undefined behavior if (quote from C99 Standard)
[t]he program attempts to modify a string literal.
For reference, from the C99 Standard, the strcat
function has the prototype
#include <string.h>
char *strcat(char * restrict s1, const char * restrict s2);
and description
The strcat function appends a copy of the string pointed to by s2
(including the terminating null character) to the end of the string
pointed to by s1. The initial character of s2 overwrites the null
character at the end of s1. If copying takes place between objects
that overlap, the behavior is undefined.
You should place "Hello"
in a char
array large enough to also store the name that you want to concatenate if you want your desired output. For example,
#include <stdio.h>
#include <string.h>
#define STRINGIZE(x) #x
int main(void) {
char *name = "David";
char a[12] = STRINGIZE(Hello) " ";
puts(strcat(a, name));
return 0;
}
Output
Hello David
The character array, a
, has 12 elements so that it can contain all 5 characters in Hello
, the space character,
, all 5 characters in David
, plus the null character.
Note that 12 is the minimum length for the array a
to hold the string "Hello David"
(11 characters plus 1 for the null character). You will need a
to be larger if the names will be larger. If you know, from your input, the largest possible name, then you can make a
large enough to hold the largest possible name (plus Hello
plus the null character).
Alternatively, first, you decide on some arbitrary length for the array a
. Then, you use the strncat
function in a safe way such that strncat
only writes to elements of the array a
. The strncat
function essentially does the same thing as strcat
except it allows you to specify a third argument which represents the maximum number of characters from s2
to append to s1
(the null character that strncat
automatically appends to the result of the concatenation is not included in this number). In the case that you specify a third argument that instructs strncat
to never write past the end of the array a
, if the name is too long, the full name will not be stored in a
, but this is better and safer than trying to write past the end of the array, which is what strcat
would have attempted.
Again, for reference (from C99 Standard), the strncat
function has the prototype
#include <string.h>
char *strncat(char * restrict s1, const char * restrict s2,
size_t n);
and description
The strncat function appends not more than n characters (a null
character and characters that follow it are not appended) from the
array pointed to by s2 to the end of the string pointed to by s1. The
initial character of s2 overwrites the null character at the end of
s1. A terminating null character is always appended to the result. If
copying takes place between objects that overlap, the behavior is
undefined.