Creating substrings C: loop with assignment operator VS strncopy, which is better?

It might be a little pointless, but I'm curious what you guys think about it. I repeat the line with the pointers and want to pull a short substring out of it (putting the substring in a previously allocated temporary array). Is there any reason to use strncopy assignment or vice versa? I.e

#include <stdlib.h> #include <stdio.h> #include <string.h> int main() { char orig[] = "Hello. I am looking for Molly."; /* Strings to store the copies * Pretend that strings had some prior value, ensure null-termination */ char cpy1[4] = "huh\0"; char cpy2[4] = "huh\0"; /* Pointer to simulate iteration over a string */ char *startptr = orig + 2; int length = 3; int i; /* Using strncopy */ strncpy(cpy1, startptr, length); /* Using assignment operator */ for (i = 0; i < length; i++) { cpy2[i] = *(startptr + i); } /* Display Results */ printf("strncpy result:\n"); printf("%s\n\n", cpy1); printf("loop result:\n"); printf("%s\n", cpy2); } 

It seems to me that strncopy is both less typed and easier to read, but I have seen people advocate for the loop. Is there any difference? Does it even matter? Assume that this is for small values โ€‹โ€‹of i (0 <i <5), and the completion of zero-output is guaranteed.

Refs: Strings in c, how to get a substring , How to get a substring in C , Difference between strncpy and memcpy?

+4
source share
4 answers

Although this may seem inconsistent, there are more optimized ways to copy a string than using the assignment operator in a loop. For example, IA-32 provides the REP prefix for MOVS , STOS , CMPS , etc. To process strings, and they can be much faster than a loop that copies one char at a time. An implementation of strncpy or strcpy can use such hardware-optimized code to achieve better performance.

+3
source

strncpy(char * dst, char *src, size_t len) has two peculiar properties:

  • if (strlen(src) >= len) : the resulting string will not be nul-terminated.
  • if (strlen(src) < len) : the end of the line will be filled / padded with "\ 0".

The first property will force you to actually check if (strlen(src) >= len) and act accordingly. (or brutally set the trailing character to nul using dst[len-1] = '\0'; as @Gilles does above). Another property is not particularly dangerous, but can spill many cycles. Imagine:

 char buff[10000]; strncpy(buff, "Hello!", sizeof buff); 

which concerns 10000 bytes, where you need to touch only 7.

My advice:

  • A: if you know the sizes, just memcpy(dst,src,len); dst[len] = 0; memcpy(dst,src,len); dst[len] = 0;
  • B: if you don't know the sizes, get them somehow (using strlen and / or sizeof and / or allocated size for dynamically allocated memory). Then: goto A above.

Since the strncpy () version must already know the sizes (and checks for them!) For safe operation, the memcpy () version is not more complex or more dangerous than the strncpy () version. (technically this is even a little faster because memcpy () should not check the bytes of '\ 0')

+4
source

As long as you know that your lengths are "in range" and everything is correctly terminated by nul, then strncpy better.

If you need to get a length check, etc., a loop may be more convenient.

+1
source

An assignment cycle is a bad idea because you are reinventing the wheel. You can make a mistake, and your code is likely to be less efficient than the code in the standard library (some processors have optimized instructions for copies of memory, and optimized implementations usually at least copy word by word, if possible).

However, note that strncpy not a well-rounded wheel. In particular, if the string is too long, it does not add a null byte to the destination. The BSD strlcpy function is better developed, but not available everywhere. Even strlcpy not a panacea : you need to get the buffer size correctly and know that it can trim the string.

A portable way to copy a truncated string if the string is too long is to call strncpy and always add a terminating null byte. If the buffer is an array:

 char buffer[BUFFER_SIZE]; strncpy(buffer, source, sizeof(buffer)-1); buf[sizeof(buffer)-1] = 0; 

If the buffer is specified by pointer and size:

 strncpy(buf, source, buffer_size-1); buf[buffer_size-1] = 0; 
0
source

Source: https://habr.com/ru/post/1432498/


All Articles