[C]memcmp


memcmp함수는 두문자열을 바이트단위로 비교하는 함수입니다.


1️⃣ 함수원형

< memset >

void *memcmp(const void *str1, const void *str2, size_t size)

2️⃣ 헤더파일, 반환값

  • 반환값:

    조건반환값(size_t)
    str1 > str21 or 양수
    str1 == str20
    str1 < str2-1 or 음수
  • 헤더파일: <string.h>


3️⃣ 함수구현

< memcmp >

int memcmp(const void *str1, const void *str2, size_t size)
{
	const unsigned char	*s1;
	const unsigned char *s2;

	s1 = str1;
	s2 = str2;
	while (size-- > 0)
	{
		if (*s1 != *s2)
			return (*s1 - *s2);
		s1++;
		s2++;
	}
	return (0);
}

4️⃣ 특징 & 주의사항

  1. size의 값이 음수가 되면 버퍼오버플로우(size_t는 unsigned형으로 선언되어 있기 때문)가 일어납니다. 컴파일러에 따라서 경고메시지를 출력해주기도 합니다. 하지만 대부분의 컴파일러에서 오버플로우난 상태로 함수가 실행됩니다.
  2. 바이트단위로 비교를 하기 때문에 255를 초과하는 int형정수를 사용할 경우 예상치 못한 결과를 얻게됩니다.(리틀 엔디언일 경우)
  3. void형으로 인자를 받고 바이트단위로 비교하기 때문에 이차원 배열도 비교가 가능합니다.

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

1. < 255를 초과하는 int형정수를 사용할 경우(특징2) >
#include <stdio.h>
#include <string.h>

int main(void)
{
	int num1[] = {1, 2, 3, 5};
	int num2[] = {1, 2, 3, 256};

	printf("%d\n", memcmp(num1, num2, 4*sizeof(int)));
}
/* ---결과--- */
5(리눅스), 1(윈도우)
  • 기대값: -256(리눅스), -1(윈도우)
  • 출력값: 5(리눅스), 1(윈도우)
  • 원인: 바이트단위로 검사
  • 이유: 4번째 원소에서 차이가나는데 리틀엔디언 기준으로 메모리를 살펴보면 ‘(int)5’는 05 00 00 00 ‘(int)256’은 00 01 00 00으로 스텍에 쌓여있기 때문에 앞의 1바이트 부분만 검사하고 결과를 출력하게 됩니다.

  • 결론: 1byte단위로 값을 비교하는 형식이기 때문에 리틀엔디언 환경에서는 1byte의 크기가아닌 자료형을 사용하면 예상치 못한 결과가 생길 수 있습니다. 빅엔디언 환경에서는 int형 범위내의 모든정수가 비교가능하지만 리틀엔디언환경에서는 255이하의 int형정수만 사용하는 것이 좋습니다.

2. < 2차원배열을 비교할 경우(특징3) >
(1)char형 2차원 배열
int mainv(void)
{
	char word1[2][5] = {"same", "abcd"};
	char word2[2][5] = {"same", "abcb"};
	printf("%d\n", memcmp(word1, word2, sizeof(word1)));
}
/*---출력---*/
1(윈도우), 2(리눅)


(2)int형 2차원 배열
int main(void)
{
	int ss[2][5] = { {1, 2, 3, 4} , {1, 2, 3, 4} };
	int ss2[2][5] = { {1, 2, 3, 4} , {1, 2, 3, 7} };

	printf("%d\n", memcmp(ss, ss2, sizeof(ss)));
}
/*---출력---*/
-1(윈도우), -3(리눅스)


(3)포인트 배열
int main(void)
{
	int num1[] = {1, 2, 3, 5};  //num2보다 큰주소에 위치
	int num2[] = {1, 2, 3, 6};  //num1보다 작은주소 위치
	int *ss[1];
	int *ss2[1];

	ss[0] = num1;
	ss2[0] = num2;
	printf("%d\n", memcmp(ss, ss2, sizeof(ss)));
}
/*---출력---*/
1(윈도우), 16(리눅스)
/*---num1, num2주소---*/
// num1의 주소가 num2의 주소보다 16(int형원소 4개)만큼 큽니다.
  • 위의 3가지 케이스처럼 2차원배열도 memcmp함수로 비교가 가능합니다. 하지만 정확한 비교를 위해서는 두배열의 메모리가 형태가 같은 것이 좋습니다.




© 2021.02. by kirim

Powered by kkrim