2009-07-22 5 views
24

특정 시작 지점의 버퍼간에 특정 길이의 내용을 복사하려고합니다. 나는 memcpy()을 체크했으나 시작 인덱스를 지정하고 싶을 때 복사 할 내용의 길이 만 사용합니다.startIndex가있는 memcpy?

기존의 memcpy 기능을 사용하거나이를 수행 할 수있는 좋은 방법이 있습니까?

+0

참고 : memcpy는 C이며 C++가 아닙니다. 내가 자주 사용하지만 memcpy가 타입 안전, 상속, 예외로서 주요한 C++ 개념과 완전히 대조적 인 것은 의심의 여지가 없다. memcpy로 모든 것을 망칠 아주 쉽습니다. –

+3

memcpy는 C++ 표준 –

+0

의 일부입니다. 확실히 C 헤더를 통해 제공됩니다. 그러나 C++ 자체는'std :: copy'를 제공합니다. 이것은 일반적으로'memcpy'와 같거나 _better_이며, 더 유연하고, 또 타입 안전합니다. –

답변

5

주소에 오프셋을 추가하기 만하면됩니다. 당신이 N 번째 바이트로 시작하는 버퍼를 복사하려는 경우 예를 들어, :

memcpy(destination, source + N, sourceLen - N); 

이것은 destination에 복사합니다. 목적지를 오프셋하려는 경우 - 오프셋을 둘 다에 추가하십시오.

memcpy(destination + N, source + N, sourceLen - N); 
+1

소스가 1 바이트 길이의 유형을 가리키는 경우에만 작동합니다. 다른 모든 경우에는 잘못된 오프셋을 얻습니다 (void는 단순히 컴파일되지 않습니다). – JaredPar

+0

@JaredPar : 참이면 더 많은 산술 연산이 필요합니다. – sharptooth

23

버퍼의 주소에 원하는 오프셋을 추가하기 만하면됩니다.

char abuff[100], bbuff[100]; 
.... 
memcpy(bbuff, abuff + 5, 10); 

이것은 abuff [5]에서 시작하여 bbuff까지 10 바이트를 복사합니다.

+0

이것은 다소기만적인 예입니다. 그것은 char가 길이가 1 바이트가 될 것이기 때문에 작동합니다. size <> 1 인 다른 모든 유형의 경우이 코드는 컴파일되지만 잘못 실행됩니다 (coures를 제외하고). – JaredPar

+0

@ JaredPar : IMHO 닐의 대답은 전적으로 정확합니다. 질문은 "... 시작 색인을 지정하고 싶습니다."라고 말합니다. 상수를 포인터에 추가하면 가리키는 유형의 크기가 고려됩니다. 나는. 'int * p ='...; p + = 5; 'p'point sizeof (int) * 5 바이트를 더 만들 것입니다. –

+0

char가 전혀 언급되지 않았지만 버퍼라는 용어는 약간 의미가 있음을 의미합니다. – CsTamas

2

소스 포인터를 지정된 바이트 수만큼 간단히 업데이트 할 수 있기 때문에 색인이 필요하지 않습니다. 다음 랩퍼가 트릭을 수행해야합니다.

void* memcpy_index(void *s1, const void *s2, size_t index, size_t n) { 
    s2 = ((char*)s2)+index; 
    return memcpy(s1, s2,n); 
} 
+0

인덱스는 바이트 인덱스이고 n은 바이트 카운트라고 가정하고 있지만 다른 대부분의 사람들은 다른 방법으로 읽습니다. 이 경우 s1과 s2는 char * – Indy9000

+0

@Indeera로 입력 될 수 있습니다. 크기 필드 n과 같은 인덱스는 바이트로 지정됩니다. – JaredPar

1

포인터를 시작 색인으로 간단히 늘리십시오.

const unsigned char * src = reinterpret_cast<const unsigned char*>(your source); 
unsigned char * dest = reinterpret_cast<unsigned char *>(your dest); 
memcpy(dest, src + offset, len); 

어떤 메모리 접근 오류를 방지하기 위해 STL 컬렉션을 사용하는 방법에 대해?

0

인덱스를 버퍼의 주소에 추가하고 소스 매개 변수로 memcpy()으로 전달하면됩니다 (예 : 또한 버퍼에 계정으로 방어 적이기의 길이 (3) 매개 변수를() 항목의 유형을

char a[10], b[20]; 
::memcpy(a,b+2,10); 

나 버퍼의 3 항목을 복사하면 4를 넣어하여야하므로 4의 int를 복사 할 바이트에 *를 sizeof (INT) - 때문에 포인터를 arithmetics의 종류가 시작 주소를 중요하지 않습니다 아마도 32 비트 시스템에서 (16되지만, :.

int a[10], b[10]; 
::memcpy(a+2, b, 2*sizeof(int)); 
// a+2 will be address of 3rd item in buffer a 
// not address of 1st item + 2 bytes 
51

난 항상 구문을 선호

memcpy(&dst[dstIdx], &src[srcIdx], numElementsToCopy * sizeof(Element)); 
+3

Ditto. 낮은 수준에서 메모리를 복사 할 때는 너무 자세하게 표현할 수 없습니다. 당신의 indicies를 잘 명명하면 라인에서 5 개월 후에 일어난 일을 정확하게 기억할 수있는 기회가 증가합니다. –

0

당신은 fu를 가질 수 있습니다. 아래처럼.

template<typename T> 
T* memcopy_index(T* dst,T* src,unsigned int index, unsigned int element_count) 
{ 
    return (T*)memcpy(dst,src + index, element_count * sizeof(T)); 
} 

은 아래와 같이 사용할 수 있습니다

int src[]={0,1,2,3,4,5,6}; 
int dst[15]; 

memcopy_index(dst,src,2,5); //copy 5 elements from index 2 

당신은 대상 버퍼가 요소를 복사 할 수있는 충분한 공간이 있는지 확인해야합니다.

0

C++를 사용하는 경우 memcpy() 대신 std :: copy()를 사용하는 것이 좋습니다. std :: copy는 iterators처럼 쉽게 포인터를 취할 수 있습니다.

int src[20]; 
int dst[15]; 

// Copy last 10 elements of src[] to first 10 elements of dst[] 
std::copy(src+10, src+20, dst); 

memcpy()와 마찬가지로 포인터가 유효한지 확인하는 것은 귀하의 책임입니다.

참고. 당신의 사용이 성능에 결정적이라면, 다른 답변에 자세히 나와있는 것처럼 memcpy()를 찾을 수 있지만,별로 그렇지 않을 수도 있습니다.

+1

당신의 구현은 평범한 오래된 객체에 대해 memcpy를 사용하여 std :: copy를 자유롭게 구현할 수 있습니다. –

+0

알아두면 좋을 것 같습니다. 감사. +1 –

1

이 사이트는 익명의 답변 외에 익명의 후속 조치를 허용하는 방법이 필요합니다.

"인덱스"가 1 바이트 단위 여야한다는 이유가 여러 번 나오는 이유는 무엇입니까? 그것은 대회의 정반대입니다. "인덱스"는 일반적으로 심볼릭 (symbolic)이며 물리적 바이트 오프셋은 배열의 요소의 크기에 의해 결정됩니다. (또는 벡터의 경우 배열의 실제 레이아웃이 없더라도 memcpy()는 관련이 없습니다. 코스).

그래서 어레이의 5 번째 요소는 "인덱스"5하지만 가지고 배열 char 형이면

  • 을 그 "인덱스"의 바이트 오프셋은 5.
  • 은 배열이 short (x86의 경우)이면 "인덱스"의 바이트 오프셋은 10입니다.
  • 배열의 유형이 int (x86의 경우)이면 "인덱스"의 바이트 오프셋은 20입니다.
  • 배열이 일부 대형 48 바이트 객체 유형 인 경우 해당 "색인"의 바이트 오프셋은 240입니다.

특정 요소에 액세스하는 올바른 방법은 측면에서 두 가지입니다. 중요한 부분은 차이점을 이해하고 하나를 선택하고 코드를 수정하는 것입니다.

단어의 의미에

, 나는 차라리 읽을 것입니다 :

void* memcpy_offset(void *s1, const void *s2, size_t offset, size_t n); 

보다 :

void* memcpy_index(void *s1, const void *s2, size_t index, size_t n); 

내가 아이디어를 찾을 완전히 일반적인 무효 *는 "인덱스를 가질 수있는 "오해하기 쉽다. (우리가 여기에있는 동안 "dest"와 "source"또는 "in"과 "out"은 "s1"과 "s2"보다 덜 모호합니다. 코드는 자명 할 때 많은 주석을 필요로하지 않습니다. 변수 이름.)

관련 문제