"바이트 수"를 0으로 설정하여 memcpy () 및 memmove ()를 호출 할 수 있습니까?


102

나는 actully 이동에 아무것도 없을 때 내가 함께 복사 / 치료의 경우에 필요합니까 memmove()/memcpy() 에지의 경우와 같은

int numberOfBytes = ...
if( numberOfBytes != 0 ) {
    memmove( dest, source, numberOfBytes );
}

또는 확인하지 않고 함수를 호출해야

int numberOfBytes = ...
memmove( dest, source, numberOfBytes );

이전 스 니펫의 확인이 필요합니까?


6
질문은 free와 같은 함수에 대한 null 포인터를 약간 확인하는 것을 상기시킵니다. 필요하지는 않지만 거기에 대한 생각을 보여주기 위해 댓글을 달겠습니다.
두꺼비

12
@Toad : 코드를 복잡하게 만드는 것 외에 어떤 용도로 사용됩니까? 누군가의 코드를 읽을 때 원래 프로그래머가 "실제로 필요하지 않은이 작업을 수행하려고 생각했지만 불필요하기 때문에 그렇게하지 않았다"는 것을 알 필요가 없습니다. 포인터가 해제 되는 것을 본다면 그것이 null이 될 수 있다는 것을 알고 있습니다. 그래서 "should I check for null"이라는 주제에 대한 원래 프로그래머의 생각을 알 필요가 없습니다. 0 바이트를 복사하는 경우도 마찬가지입니다.memcpy
jalf

8
@jalf : stackoverflow에 대한 질문이라는 사실은 사람들이 의심하게 만듭니다. 코멘트를 추가하는 것은 당신을 도울 수 있지만,되지 않을 수도 적은 지식이 힘 도움말 사람
두꺼비

2
@Toad 네, 왜 필요한지 확인하는 것이 원칙적으로 가치가없는 이유를 명시 적으로 설명하는 주석입니다. 동전 의 다른 측면은이 특정 예제가 각 프로그래머가 한 번만 답을 배우면되는 표준 라이브러리 기능을 포함하는 일반적인 경우라는 것입니다. 그런 다음 읽은 모든 프로그램에서 이러한 검사가 필요하지 않음을 인식 할 수 있습니다. 들어 이유는, 내가 코멘트를 생략 할 것입니다. 이와 같은 여러 호출이있는 코드베이스는 주석을 각각에 복사하여 붙여 넣거나 일부 호출에만 임의로 사용해야합니다. 둘 다 추악합니다.
Mark Amery

답변:


145

C99 표준 (7.21.1 / 2)에서 :

로 선언 된 인수 size_t n가 함수에 대한 배열의 길이 를 지정하는 경우 해당 함수 n에 대한 호출에서 값 0을 가질 수 있습니다. 이 하위 절의 특정 함수에 대한 설명에서 달리 명시 적으로 언급되지 않는 한, 그러한 호출에 대한 포인터 인수는 7.1.4에 설명 된대로 여전히 유효한 값을 가져야합니다. 이러한 호출에서 문자를 찾는 함수는 발생을 찾지 못하고 두 문자 시퀀스를 비교하는 함수는 0을 반환하며 문자를 복사하는 함수는 0 개의 문자를 복사합니다.

그래서 대답은 아니오입니다. 확인이 필요하지 않습니다 (또는 예, 0을 통과 할 수 있음).


1
포인터가 배열의 마지막 요소 다음의 위치를 ​​가리키는 경우 이러한 함수의 목적에 대해 "유효한"것으로 간주됩니까? 그러한 포인터는 합법적으로 따를 수는 없지만, 하나를 빼는 것과 같은 다른 포인터 같은 일을 안전하게 할 수 있습니다.
supercat 2011

1
@supercat : 예, 배열의 끝을 지나는 포인터를 가리키는 포인터는 해당 배열 내의 다른 포인터 (또는 끝을 지나는 포인터)와의 포인터 산술에 유효하지만 역 참조 할 수 없습니다.
Mike Seymour 2011

@MikeSeymour : 인용이 반대 답을 의미하지 않아야합니다. 확인이 필요하고 널 포인터로 0을 전달할 수 없습니까?
neverhoodboy

7
@neverhoodboy : 아니요, 따옴표에는 " n값이 0 일 수 있음 " 이 명확하게 나와 있습니다. 널 포인터를 전달할 수 없다는 것은 맞지만 질문이 요구하는 것은 아닙니다.
마이크 시모어

1
@MikeSeymour : 내 잘못입니다. 정말 죄송합니다. 문제는 포인터가 아닌 크기에 관한 것입니다.
네버 후드 보이

5

@You가 말했듯이 표준은 memcpy와 memmove가 문제없이이 경우를 처리하도록 지정합니다. 그들은 일반적으로 어떻게 든 다음과 같이 구현되기 때문에

void *memcpy(void *_dst, const void *_src, size_t len)
{
    unsigned char *dst = _dst;
    const unsigned char *src = _src;
    while(len-- > 0)
        *dst++ = *src++;
    return _dst;
}

함수 호출 이외의 성능 저하도 없어야합니다. 컴파일러가 이러한 함수에 대한 내장 / 인라이닝을 지원하는 경우 추가 검사는 그 동안 이미 검사가 수행 되었기 때문에 코드를 조금 더 느리게 만들 수도 있습니다.


1
이 함수는 아마도 c보다 훨씬 더 나은 메모리 전송을 최적화 할 수있는 어셈블리로 만들어 졌다고 생각합니다
Toad

"어딘지 모르게" :) 실제로 내가 본 거의 모든 구현은 어셈블리에 있으며 기본 단어 크기 (예 : x86의 uint32_t)를 사용하여 대부분의 비트를 복사하려고하지만 대답의 본질은 변경되지 않습니다. : 시작하기 전에 큰 계산이 필요하지 않은 while 루프이므로 이미 확인이 완료되었습니다.
Matteo Italia

9
-1, 일반적인 구현은 0 인수로 이러한 함수 (C 함수로 구현되지 않을 수도 있음)를 호출하는 것이 유효한 C인지 여부와 무관합니다.
R .. GitHub STOP HELPING ICE

4
그것이 유효한 C라는 사실은 이미 다른 답변에서 다루었습니다. "@You가 말했듯 이 표준 은 memcpy와 memmove가 문제없이이 경우를 처리해야한다고 지정합니다". 성능상의 이유로 memcpy를 len = 0으로 호출하는 것을 두려워해서는 안된다는 사실에 대한 제 의견을 추가했습니다.이 경우 거의 비용이 들지 않는 호출이기 때문입니다.
Matteo Italia
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.