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.