strcat_s and char pointer newbie issue

1.5k views Asked by At

I'm doing simple c excercise using visual studio. Using strcat_s function I receive a violation exception thru this code:

char *str1;
str1 = (char *)malloc(20);
*str1 = "Ciao ";
char *str2 = "Marco";
strcat_s(str1, sizeof(str1), str2);
printf("%s", str1);

Now, if I use a predefined array whith a fixed size, strcat_s works perfectly. How can I use pointers to char instead of array to make it work?

Any other solution or tip will be very appreciated.

Thank you in advance.

2

There are 2 answers

0
Phil Fighter On

You have to copy the strings firstly into the allocated memory. If you like to know the length of a string use strlen(). sizeof() returns the size of the datatype in byte. In your case it is a pointer (4 byte on 32bit, 8 byte on 64bit machines). The following code should work properly:

char *str1 = (char *)malloc(20);
strcpy(str1,"Ciao ");
char *str2 = (char *)malloc(20);
strcpy(str2,"Marco ");
strcat(str1, str2);
printf("%s", str1);
0
Stephan Lechner On

There are some issues with your code, and there are some general notes on strcat_s.

Your code str1 = (char *)malloc(20); *str1 = "Ciao " does not copy Ciao; *str is a single character at the first position of str, and your expression converts string literal "Ciao " (which is a pointer to a sequence of characters) to some single character (T in this case; surprising, isn't it?). One would need to use strcpy instead. An array, like char buffer[20] = "Ciao ", in contrast, works, because this (special) case is not an assignment but an initialiser of an array.

Your code sizeof(str1) gives you the size of a pointer value, which is probably 4 or 8, and has nothing to do with the actual size of the content or the memory block reserved. One should use strlen instead.

Concerning strcat_s, one should consider that it is not available on all platforms and that you have to be aware of it's special behaviour. For example, if you call strcat_s(somebuffer, 3, "somestrlongerthan3"), which exceeds the maximum length of 3 as provided, somebuffer will be an "empty" string (i.e. the first character will be set to \0.

I'd suggest to use strncat or snprintf instead. See the following variants:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main () {

    char c = "Ciao ";  // Gives a compiler warning and yields 'T'

#define maxlen 20

    // Variant 1: start with initialized buffer, yet no "pointer" and dynamic allocation
    char resultBuffer[maxlen] = "Ciao ";
    size_t charactersRemaining = maxlen-strlen(resultBuffer)-1;
    strncat(resultBuffer, "Marco", charactersRemaining);

    // Variant 2: use dynamically allocated buffer and snprintf, with constant "Ciao".
    char *resultBuffer2 = malloc(maxlen);
    const char* second2 = "Marco";
    snprintf(resultBuffer2, maxlen, "Ciao %s", second2);

    // Variant 3: use dynamically allocated buffer and snprintf, with probably variable "Ciao" and "Marco"
    char *resultBuffer3 = malloc(maxlen);
    const char* first3 = "Ciao";
    const char* second3 = "Marco";
    snprintf(resultBuffer3, maxlen, "%s %s", first3, second3);

    return 0;
}