memcpy 와 strncpy의 차이점은 무언가요??

passion의 이미지

구조체 멤버(insca.st_code : insca는 global로 선언된 구조체명 )에서
구조체 멤버(xx_insca->st_code : xx_insca 는 인자로 넘겨온 구조체형 char pointer) 로 copy를 하는데 memcpy를 하면 xx_insca->st_code의 값은 물론이고 그 뒤로부터 값들이 원치않는 값으로 깨지거나 밀려서 출력됩니다.
물론 구조체 멤버의 길이는 모두 같습니다.
하지만 strncpy를 이용해서 copy를 하면 제값이 제대로 복사되어 올바른 값이
나오는 데 memcpy와 strncpy의 특별한 다른점이 있습니까?
아니면 사용상의 주의가 필요한 점이라도....
부탁드립니다. 몇일을 낑낑대고 있답니다. :roll:

winner의 이미지

strncpy 는 n 개의 문자이전에 null 문자가 들어오면 복사를 끝내는 것 이외에는 제가 아는 차이점은 없습니다.

mastercho의 이미지

조금 차이점은 있죠 -_-

strcpy는 널 검사를 하기때문에
좀 느리고

memcpy는 메모리크기를 받아 그거대로 바로 복사하기때문에
더 빠르다는거......

승자는 자기보다 우월한 사람을 보면 존경심을 갖고 그로부터 배울 점을 찾지만 패자는 자기보다 우월한 사람을 만나면 질투심을 갖고 어디 구멍난 곳이 없는지 찾는다.
- 하비스

passion의 이미지

MAKE_SAM(NGS_SAM *XX_NGS_SAM)
{
memcpy(INSCA.ST_EXPRO_TICKET,
XX_NGS_SAM->ST_EXPRO_TICKET,
sizeof(XX_NGS_SAM->ST_EXPRO_TICKET ));

memcpy(INSCA.ST_MANUA_TICKET ,
XX_NGS_SAM->ST_MANUA_TICKET,
sizeof(XX_NGS_SAM->ST_MANUA_TICKET ));
}

NGS_SAM 은 구조체 명으로서 header 화일에 선언되어 있으며,
INSCA 역시 구조체 명이고 이것 역시 header화일에 선언되어 있습니다.
함수 MAKE_SAM은 다른 sub-function에서 NGS_SAM 형태로 주소값을 받습니다.

이때 넘겨온 NGS_SAM 형태의 화일 record를 구조체 INSCA 에 일부를 넣고 싶은데 memcpy와 strncpy의 차이로 인해 난항을 격고있습니다. NGS_SAM 형태의 화일레코드를 확인차 각각의 멤버값을 출력해봤을때 값의 오류는 없었습니다. 하지만 그 값들을 INSCA의 같은이름의 멤버에 copy를 할때면 값이 깨지거나 밀리네요..

notexist의 이미지

memcpy

void *
memcpy(dst0, src0, length)
	void *dst0;
	const void *src0;
	size_t length;
{
	char *dst = dst0;
	const char *src = src0;
	size_t t;
	unsigned long u;

	_DIAGASSERT(dst0 != 0);
	_DIAGASSERT(src0 != 0);

	if (length == 0 || dst == src)		/* nothing to do */
		goto done;

	/*
	 * Macros: loop-t-times; and loop-t-times, t>0
	 */
#define	TLOOP(s) if (t) TLOOP1(s)
#define	TLOOP1(s) do { s; } while (--t)

	if ((unsigned long)dst < (unsigned long)src) {
		/*
		 * Copy forward.
		 */
		u = (unsigned long)src;	/* only need low bits */
		if ((u | (unsigned long)dst) & wmask) {
			/*
			 * Try to align operands.  This cannot be done
			 * unless the low bits match.
			 */
			if ((u ^ (unsigned long)dst) & wmask || length < wsize)
				t = length;
			else
				t = wsize - (size_t)(u & wmask);
			length -= t;
			TLOOP1(*dst++ = *src++);
		}
		/*
		 * Copy whole words, then mop up any trailing bytes.
		 */
		t = length / wsize;
		TLOOP(*(word *)(void *)dst = *(const word *)(const void *)src; src += wsize; dst += wsize);
		t = length & wmask;
		TLOOP(*dst++ = *src++);
	} else {
		/*
		 * Copy backwards.  Otherwise essentially the same.
		 * Alignment works as before, except that it takes
		 * (t&wmask) bytes to align, not wsize-(t&wmask).
		 */
		src += length;
		dst += length;
		u = (unsigned long)src;
		if ((u | (unsigned long)dst) & wmask) {
			if ((u ^ (unsigned long)dst) & wmask || length <= wsize)
				t = length;
			else
				t = (size_t)(u & wmask);
			length -= t;
			TLOOP1(*--dst = *--src);
		}
		t = length / wsize;
		TLOOP(src -= wsize; dst -= wsize; *(word *)(void *)dst = *(const word *)(const void *)src);
		t = length & wmask;
		TLOOP(*--dst = *--src);
	}
done:
	return (dst0);
}

strncpy

char *
strncpy(dst, src, n)
	char *dst;
	const char *src;
	size_t n;
{

	_DIAGASSERT(dst != NULL);
	_DIAGASSERT(src != NULL);

	if (n != 0) {
		char *d = dst;
		const char *s = src;

		do {
			if ((*d++ = *s++) == 0) {
				/* NUL pad the remaining n-1 bytes */
				while (--n != 0)
					*d++ = 0;
				break;
			}
		} while (--n != 0);
	}
	return (dst);
}

From BSD.

There is more than one way to do it...

linuxs의 이미지

passion wrote:
MAKE_SAM(NGS_SAM *XX_NGS_SAM)
{
memcpy(INSCA.ST_EXPRO_TICKET,
XX_NGS_SAM->ST_EXPRO_TICKET,
sizeof(XX_NGS_SAM->ST_EXPRO_TICKET ));

memcpy(INSCA.ST_MANUA_TICKET ,
XX_NGS_SAM->ST_MANUA_TICKET,
sizeof(XX_NGS_SAM->ST_MANUA_TICKET ));
}

다음과 같이 바꿔보세요..

MAKE_SAM(NGS_SAM *XX_NGS_SAM)
{
memcpy(&INSCA.ST_EXPRO_TICKET,
&XX_NGS_SAM->ST_EXPRO_TICKET,
sizeof(XX_NGS_SAM->ST_EXPRO_TICKET ));

memcpy(&INSCA.ST_MANUA_TICKET ,
&XX_NGS_SAM->ST_MANUA_TICKET,
sizeof(XX_NGS_SAM->ST_MANUA_TICKET ));
}

꿈은 이루어진다.

전웅의 이미지

mastercho wrote:
조금 차이점은 있죠 -_-

strcpy는 널 검사를 하기때문에
좀 느리고

memcpy는 메모리크기를 받아 그거대로 바로 복사하기때문에
더 빠르다는거......

만들기 나름입니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

windy96의 이미지

전웅 wrote:
mastercho wrote:
조금 차이점은 있죠 -_-

strcpy는 널 검사를 하기때문에
좀 느리고

memcpy는 메모리크기를 받아 그거대로 바로 복사하기때문에
더 빠르다는거......

만들기 나름입니다.

전웅님 말씀은 NULL 검사를 하지 않는 strcpy, strncpy가 있다는 말씀이신가요?

만약 그런 library가 있다면.. de facto standard에서 어긋나는 거지요... memcpy, bcopy가 NULL이라고 copy를 안 해도 마찬가지구요.
확인 부탁드립니다.

sangwoo의 이미지

7.21.2.4 The strncpy function
    Synopsis
1        #include <string.h>
          char *strncpy(char * restrict s1, const char * restrict s2, size_t n);

    Description
2        The strncpy function copies not more than n characters (characters that
                                                                 ^^^^^^^^^^^^^^^
          follow a null character are not copied) from the array pointed to by s2
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          to the array pointed to by s1. If copying takes place between objects
          that overlap, the behavior is undefined. 3 If the array pointed to by s2
          is a string that is shorter than n characters, null characters are
          appended to the copy in the array pointed to by s1, until n characters
          in all have been written.

제 생각에도 null character 체크를 해야 할것 같습니다.
실제로 FreeBSD libc와 glibc-2.3.2에서도 그렇게 하고 있군요..

PS. 생각해 보니 카피하고 나서 체크후 지워도 될 꺼 같다는 생각도 드는군요;
음.. 저 괄호속 문장이 src와 dst를 결과적으로 비교할 때 성립해야 한다는 건지,
아니면 카피하는 행위 자체를 하지 말라는 건지 헷갈리네요. 어느 경우에건 한번
이상의 null character 체크는 해야 하겠지만요.

----
Let's shut up and code.

전웅의 이미지

windy96 wrote:
전웅님 말씀은 NULL 검사를 하지 않는 strcpy, strncpy가 있다는 말씀이신가요?

짧은 제 글이 오해를 불렀네요. "성능" 에 대한 단정이 있어서는 안 된다는
뜻이었습니다. strncpy 와 memcpy 사이의 선택은 "성능" 이 아닌 "기능" 에
의해 이루어져야 합니다. <string.h> 함수들의 명칭이 갖는 prefix (str,
strn, mem) 는 (물론, 역사적 전통을 가지고 있는 것들이지만) 기능에 의존
하여 group 되어 있습니다.

참고로, C 문맥에서 NULL 은 null character 가 아니라 null pointer
constant 를 의미합니다.

windy96 wrote:
만약 그런 library가 있다면.. de facto standard에서 어긋나는 거지요... memcpy, bcopy가 NULL이라고 copy를 안 해도 마찬가지구요.
확인 부탁드립니다.

만약, str* 함수들이 null character 검사를 하지 않는다면 (혹은 그런 것
처럼 작동한다면) de facto standard 뿐 아니라 de jure standard 도 지키
지 않은 것입니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

winner의 이미지

passion 씨가 작성하신 것과 linuxs 씨가 작성하신 code 가 다르게 동작하나요?

memcpy 가 잘못되는 이유를 모르겠습니다.

질문이 있는데 st_code member 는 당연히 char 배열인가요?
혹시 char * 를 쓰시는 것은?......

물론 적당히 동적할당하고 해제해주면 문제는 없겠습니다만...

linuxs 님이 작성하신 것이 제대로 동작한다면 좋겠지만 안된다면 INSCA 구조체 template 정의부가 보고 싶군요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.