memcpy and string literal. does it check and consider null termination -- C - c

I have a code
char str1[15];
char str2[15];
memcpy(str1,"abcdef",6);
memcpy(str2,"abcdef",6);
so str1 should have null termination at index 7.
but when I do printf("--%d--",strlen(str1)); it prints --9-- which is why its making me think that memcpy is not considering null termination when copy into str1 the string literal `"abcdef".
so shouldnt it also read null termination or is something I did in printf gives me print --9--?

memcpy just copy a number of bytes, whatever they are. In your case, it copies 6 bytes from a string of 6 characters and hence do not copy the null byte at the end of string.
Better code could be written.
Given:
char str1[15];
char str2[15];
char *p = "abcdef";
This will copy "abcdef" and the nul byte to str1 and str2:
memcpy(str1, p, strlen(p) + 1);
memcpy(str2, p, strlen(p) + 1);
But this is not very good because str1 and str2 array could be overflown if the string is to long!
It is much better to use strncpy which copies the string, taking account of the nul terminating byte, the length of the string and the maximum length of the destination:
strncpy(str1, p, sizeof(str1));
strncpy(str2, p, sizeof(str2));
Warning: If there is no null byte among the first n bytes of the source, the string placed in destination will not be null-terminated. See strncpy man page.

void * memcpy( void *destination, const void *source, size_t num ); just copies num bytes of memory, pointed by source, to another memory pointed by destination pointer.
The methods which deal with copying of null-terminated strings are
char * strcpy ( char *destination, const char *source);
char * strncpy ( char *destination, const char *source, size_t num);
Based on your example, you need to use strncpy:
char str1[15];
char str2[15];
strncpy(str1,"abcdef",7);
strncpy(str2,"abcdef",7);
str1 and str2 will hold "abcdef" at the end.
If you just want to copy the whole string up to the size of str1 or str2 then you can do the following
#define STR_LEN 15
char str1[STR_LEN];
char str2[STR_LEN];
strncpy(str1,"abcdef", STR_LEN);
strncpy(str2,"abcdef", STR_LEN);
NOTE:
As the documentation of strncpy states:
No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

Related

explanation of the souce code of strcat()

char *
STRCAT(char *dest, const char *src)
{
strcpy(dest + strlen(dest), src);
return dest;
}
what's the meaning of the code :dest + strlen(dest)?
and when I use the code like below:
#include <stdio.h>
#include <string.h>
void main()
{
char s[10]= "123456789";
char str[10] = " 123456789";
strcat(s,str);
printf("%s\n",s);
printf("%d",sizeof(s));
}
why the string s didn't overflow and the sizeof(s) did not change?
what's the meaning of the code :dest + strlen(dest)
It calculates the pointer to the end of the dest because with strcat you want to append the second string to the end of the first. It similar to:
size_t l = strlen(dest);
char *p = &dest[l]; // dest + l pointer arithmetic.
strcpy(p, src);
why the string s didn't overflow and the sizeof(s) did not change?
s is overflowing, because after strcat is done, your string is now 20 characters long, while it holds only room for 10 characters. This invokes undefined behavior.
sizeof doesn't change, because it is determined at compile time, so it will always show the same value.
strcat and STRCAT are two different functions.:)
I think you mean the function name strcat instead of STRCAT in this declaration
char *
strcat(char *dest, const char *src)
{
strcpy(dest + strlen(dest), src);
return dest;
}
This function is designed to deal with strings that is with sequences of characters terminated by the zero character '\0'.
The function strlen returns the number of characters in a string before the terminating zero character '\0';.
So the expression dest + strlen(dest) points to the terminating zero character '\0' of the string contained in the destination character array. Thus the function strcat can append the source string to the string stored in the destination array starting from the terminating zero.
So for example if you have a character array declared like
char dest[3] = { '1', '0' };
and the source array declared like
char src[2] = { '2', '0' };
For the array dest the function strlen( dest ) will return the value 1.
As a result dest + strlen( dest ) points to the second character of the array dest that is the zero character '0'. And this call
strcpy(dest + strlen(dest), src);
will copy characters of the string stored in the array src in the array dest starting with this position and you will get the following content of the array dest
{ '1', '2', '\0' }
In your program the expression sizeof( s ) gives the number of elements with which the array s is declared
char s[10]= "123456789"
that is 10. This value specified in the declaration of the array does not depend on the content that the array will have and is calculated at the compile time.
Pay attention to that values returned by the operator sizeof have the type size_t. So to output them using the function printf you have to use the conversion specifier zu. For example
printf("%zu\n",sizeof(s));
In your program the array str
char str[10] = " 123456789";
does not contain a string because it does not have a space to accommodate the (eleventh ) terminating zero character of the string literal used as an initializer.
On the other hand, the array s does not have a space to be able to append another string to its tail.
So your program has undefined behavior.
A valid program can look like
#include <stdio.h>
#include <string.h>
int main( void )
{
char str[] = " 123456789";
char s[10 + sizeof( str ) - 1] = "123456789";
strcat( s, str );
printf( "%s\n", s);
printf( "%zu\n", strlen( s ) );
printf( "%zu\n", sizeof( s ) );
}
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )

How to copy data from string to fields in struct

I know this code is sloppy, I'm trying to relearn string manipulation in C. If I have a string ABBCCCD and I want to store the separate letters in a struct, is there an efficient way to do so? I have some code down below to demonstrate the long way of what I'm trying to do. (Also, do I have to manually add the null-terminator when I'm doing a strncpy?)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct dst_struct {
char a[2];
char b[3];
char c[4];
char d[2];
} dst_struct_t;
int main(void) {
char* test = "ABBCCCD";
char* src = malloc(strlen(test)+1);
strncpy(src, test, strlen(test)+1);
printf("%s\n", src);
dst_struct_t dst;
strncpy(dst.a, src, 1);
strncpy(dst.b, src+1, 2);
strncpy(dst.c, src+3, 3);
strncpy(dst.d, src+6, 1);
printf("dst.a: %s\n", dst.a);
printf("dst.b: %s\n", dst.b);
printf("dst.c: %s\n", dst.c);
printf("dst.d: %s\n", dst.d);
free(src);
}
There isn't really any better way to do this, except that you don't need to copy test to src first.
You also need to add the null terminators to all the strings. It would probably be best to write a function that does both steps: strncpy() and adding the null terminator.
function copy_n(char *dest, char *src, size_t offset, size_t len) {
strncpy(src+offset, dest, len);
dest[len] = '\0';
}
int main(void) {
char* test = "ABBCCCD";
copy_n(dst.a, test, 0, 1);
copy_n(dst.b, test, 1, 2);
copy_n(dst.c, test, 3, 3);
copy_n(dst.d, test, 6, 1);
printf("dst.a: %s\n", dst.a);
printf("dst.b: %s\n", dst.b);
printf("dst.c: %s\n", dst.c);
printf("dst.d: %s\n", dst.d);
}
From the strcpy/strncpy man page:
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest. The strings may not overlap, and the destination string dest must be large enough to receive the copy. Beware of buffer overruns! (See BUGS.)
The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
The n argument of strncpy is generally meant to be the length of the destination buffer, as the point of the function is to be like strcpy but prevent overflowing the destination buffer if the source string is too long or not NULL-terminated. If used in that manner, your destination string will be NULL-terminated if the source string fits that length, otherwise the final byte of the buffer will contain the nth character of the source string.
However, the way you seem to be using strncpy is to set the exact number of characters you want to copy from the source buffer to place in the destination buffer. That is not really the intended purpose of strncpy. Instead, what you'd want to use is memcpy, since you are really not concerned with the zero-termination of the source string, but rather just copying a set number of characters from a set location. And yes, you will have to manually add the null-terminator if you use memcpy.

difference between strncpy and strxfrm

I can't seem to get my head around this, what is the basic difference between these two functions:
char *strncpy(char *str1, const char *str2, size_t count);
and
size_t strxfrm(char *str1, const char *str2, size_t count);
To me it seems they both copy count characters from str2 to str1. What I really want to know is, when should I use either of them?
The difference is in the return value:
The strcpy() and strncpy() functions return a pointer to the destination string.
Upon successful completion, strxfrm() shall return the length of the transformed string (not including the terminating null byte). If the value returned is n or more, the contents of the array pointed to by s1 are unspecified.

Do I need to assign \0 to malloc strings in c?

I have the following code to declare and assign a string on the heap.
char *string = malloc(10);
string[9] = '\0';
strncpy(string, "welcometotherealworld", 9);
printf("string: %s\n", string);
Do I have to manually set the \0\ to ensure the string ends? string[9] = '\0';
Or, does strncpy do this for me?
Two things: First malloc(10) reserves 10 bytes, string[10] addresses the eleventh byte, so that is illegal. Second: Yes you have to set string[9] to null, because according to the standard strncpy does not ensure the string is null terminated if the source string is longer than count.
strncpy does not null terminate the destination array if the length of the source string (the second argument) is greater or equal than the value of the third argument.
So here:
strncpy(string, "welcometotherealworld", 9);
strncpy will not null terminate.
welcometotherealworld is definitely longer than 9 characters, so strncpy should not implicitly add a terminating character.
strncpy(dest, source, n) copies at most n bytes from the buffer pointed to by source into the buffer pointer to by dest. However, if strlen(source) is greater than n, then strncpy will simply copy the first n bytes and will not terminate the string dest with a null byte because there is no space for it. Therefore to ensure that the buffer source is always null terminated, you must do it yourself. What you are doing will always keep your buffer pointed to by string null terminated.
strcpy will always terminate the destination string with a \0. strncpy also normally NULL terminates the string, but may not do. It copies a maximum number of bytes (n) of the string, but unfortunately (in terms of a useful ABI) does not copy in a NULL if the number of bytes to be copied (i.e. the length of the source string including the terminating NULL) exceeds the length specified (n) . So, if you copy the string "1234567890" (which is ten characters plus a NULL, so 11) and pass 10 as the last argument to strncpy, you will get an unterminated string of 10 characters.
Here are some safe routes around this:
dest = malloc(10); /* allocate ten bytes */
strncpy (dest, src, 10); /* copy up to 10 bytes */
dest[9] = 0; /* overwrite the 10th byte with a zero if it was not one already */
dest = malloc(10); /* allocate ten bytes */
strncpy (dest, src, 9); /* copy up to 9 bytes */
dest[9] = 0; /* make the 10th byte zero */
dest = calloc(10, 1); /* allocate and zero ten bytes */
strncpy (dest, src, 9); /* copy up to 9 bytes, leaving the NULL in */
To insure a proper '\0' ending, code needs to set the '\0'.
malloc() does not initialize the the data in string.
char *string = malloc(10);
strncpy(string, "welcometotherealworld", 9 /* or 10 */);
string[9] = '\0';
strncpy(char *s1, const char *s2, size_t n) writes n char to s1.
It first uses min(n, strlen(s2)) char from s2.
If more are needed, the remainder of s2 is written with null characters.

Concatenate two strings with a null in the middle

I'm trying to build a string that consists of two variables that are divided by a null terminator. It must be done this way for the custom protocol we're using.
const char* vendorChar = "3333-3333-4444-aaa3-3333";
const char* userChar = "someUsername";
char usernameString[strlen(vendorChar) + strlen(userChar) + 1];
char* uPtr = usernameString;
strcpy(uPtr, vendorChar);
strcpy(uPtr+strlen(vendorChar)+1, userChar);
When I run the above code, it only sends over the value of vendorChar and ignores userChar. When it is working it should look like
4444-2222-3333-1111\0someUsername
So far I've learned that str functions will drop the null as it sees it at the end of the string. I think I have to use memcpy to preserve it, but I can't figure out how to.
You're right in your assumption, strcpy may copy up to the middle null char,
according to this, strcpy(char *str1, const char *str2) does this:
Copies the string pointed to by str2 to str1. Copies up to and including the null character of str2. If str1 and str2 overlap the behavior is undefined.
memcpy should solve the problem as it just treats the memory as a chunk of bytes, not as a string.
strcpy signature:
char *strcpy(char *dest, const char *src);
memcpy signature:
void *memcpy(void *dest, const void *src, size_t n);
So just replace the name and add the cumulative lengths (with both null chars of course).
EDIT
To eliviate some doubts raised here, consider this code:
#include "string.h"
#include "stdio.h"
int main() {
char x[10] = {0};
char y[10];
char z[10];
x[0] = x[1] = x[5] = 'a';
memcpy(y,x,10);
strcpy(z,x);
printf ("y[5]= %s\n", &y[5]);
printf ("z[5]= %s\n", &z[5]);
return 0;
}
results is:
y[5]= a
z[5]=
So it's clear that memcpy moved the entire length, including byte [5], while strcpy did not, stopping at the null termination
const char* vendorChar = [vendorId cStringUsingEncoding: [NSString defaultCStringEncoding]];
const char* userChar = [dsUsername cStringUsingEncoding: [NSString defaultCStringEncoding]];
char usernameString[strlen(vendorChar) + strlen(userChar) + 2];
char* uPtr = usernameString;
strcpy(uPtr, vendorChar);
memcpy(uPtr+strlen(vendorChar)+1, userChar, strlen(userChar) + 1);
Changes: I added space for the trailing \0, the userChar string is copied with trailing \0 included.
Firstly, you need usernameString[] to be like -
char usernameString[strlen(vendorChar) + strlen(userChar) + 3];
because 1 is for putting "\", 1 for "0" and the other 1 is for null terminator, so becomes 3. Then use strcat() create the string you need. Like, below:
strcpy(uPtr, vendorChar);
strcat(uPtr,"\\");
strcat(uPtr,"0");
strcat(uPtr, userChar);

Resources