[C]memccpy & memmove


memccpy함수는 메모리값을 원하는 크기안에서 원하는 문자까지 복사하는 함수입니다.
memmove함수는 메모리값을 원하는 크기만큼 복사하는 함수입니다.(주소가 겹칠때 유용)


1️⃣ 함수원형

< memccpy >

void *memccpy(void *dst, const void *src, int c, size_t size)

< memmove >

void *memmove(void *dst, const void *src, size_t size)

2️⃣ 헤더파일, 반환값

  • 반환값:

    조건memccpymemmove
    성공시(문자찾을시)복사된 문자열 다음주소(dst)복사된 문자열 시작주소(dst)
    실패시(문자못찾을시)NULL포인터(0) 
    dst, src모두 NULL포인터일 때segmentation faultNULL포인터(0)
    dst, src둘중하나가 NULL포인터일 때segmentation faultsegmentation fault
  • 헤더파일: <string.h>


3️⃣ 함수구현

< memccpy >

void *memccpy(void *dst, const void *src, int c, size_t size)
{
	unsigned char       *dp;
	const unsigned char *sp;

	dp = dst;
	sp = src;
	while (size-- > 0)
	{
		*dp = *sp;
        if (*sp == (unsigned char)c)
            return (dp + 1);
        dp++;
        sp++;
	}
	return (0);
}

<memmove>

void *memmove(void *dst, const void *src, size_t size)
{
	const unsigned char	*sp;
	unsigned char		*dp;
	size_t				i;

	i = 0;
	dp = dst;
    sp = src;
	if (dp == NULL && sp == NULL)
		return (0);
	if (dp > sp)
    {
		while (size-- > 0)
			*(dp + size) = *(sp + size);
    }
	else
	{
		while (size-- > 0)
			*dp++ = *sp++;
	}
	return (dst);
}

4️⃣ 특징 & 주의사항

< memccpy >

  1. 찾고자하는 문자를 못찾을시 0을 반환하지만 복사는 이뤄집니다.
  2. size값을 dst, src의 크기보다 작게 잡아줘야 합니다.(컴파일러에 따라 경고메시지출력)
  3. 되도록이면 1바이트크기의 자료형만 사용하는 것이 좋습니다.(아래 자세한 내용)

< memmove >

  1. 첫번째인자(dst), 두번째인자(src) 둘다 NULL포인터이면 예상과 달리 대부분의 컴파일러에서 경고메시지 없이 NULL포인터를 반환하면서 정상컴파일이 되었습니다.
  2. size값을 dst, src의 크기보다 작게 잡아줘야 합니다.(컴파일러에 따라 경고메시지출력)

5️⃣ 코드예시(특이케이스)


1. < memccpy에서 1byte크기가 아닌 자료형을 사용할 경우 >

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

int main(void)
{
	int word1[20] = { 0, };
	int temp[] = {4423, 2, 3, 65281, 4};
	int *result

	result = memccpy(word1, temp, 65281, sizeof(temp));
	if (result == 0)
		printf("ss\n");
	for (int i = 0; i < 5; i++)
		printf("%d ", word1[i]);
	printf("\n");
}
/*---출력---*/
5 2 3 1 0
  • 기대값: 4423 2 3 65281 0
  • 출력값: 4423 2 3 1 0
  • 원인: 문자(c)를 찾은 지점에서 문제가 생김
  • 이유: memccpy함수는 찾을문자(int c)를 내부적으로 1byte의 메모리만 비교하여 찾습니다. (int)65281의 메모리를 리틀엔디언 기준으로 본다면 “01 ff 00 00”으로 되어있는데 앞의 1byte크기인 “01”부분만을 비교하여 찾게 되고 복사를 종료하게 됩니다.
  • 해결 방안:
    1. 3번째인자의 값에 “0xff”를 입력하면 65281의 메모리에서 “01 ff”까지 복사되어 기대값처럼 출력이 됩니다.
    2. int자료형일 경우 0 ~ 255(1byte범위)안에서만 다루는 것이 좋습니다.
      3번째 인자(c))가 0일경우 문제가 생길 확률이 큽니다.
<3번째 원소(65281)의 실제메모리>
 리틀 엔디언빅 엔디언
(int)25701 ff 00 0000 00 ff 01
4byte단위(int)로앞에서 부터 스텍에 쌓임뒤에서 부터 스텍에 쌓임
  • 결론: 예상치 못한 결과를 방지하기 위해서는 memccpy의 인자들을 1byte크기의 자료형을 사용하는 것이 좋습니다. 굳이 int형을 다루고 싶다면 0 ~255의 범위안에서 사용하는 것이 좋습니다.(또한 3번째인자(c)는 0을 사용하지 않는다)




© 2021.02. by kirim

Powered by kkrim