2012-06-13 4 views
4
int a = 10; 
int* pA = &a; 
long long b = 200; 
long long* pB = &b; 

memcpy (pB,pA,4); 
memcpy (pB+1,pA,4); 

cout<<"I'm a memcpy!: "<<*(pB)<<endl; 

memcpy로 몇 가지 테스트를 해보니 메모리가 어떻게 작동하는지 직접 가르쳐주세요. 내가하려는 것은 b =를 "1010"으로 만드는 것입니다. a에서 b까지의 값을 복사 할 수 있지만 메모리를 1 바이트 씩 오프셋하고 다른 10을 쓰려고 시도하지만 "10"만 출력합니다.memcpy 이해하기

1010 값을 얻으려면 어떻게해야합니까?

+5

'pB + 1'은 1 바이트 이상 증가시킵니다 : sizeof (long long)'바이트는 정확하게 나타납니다. – Mysticial

답변

7

몇 가지 문제가 약자로는 :

  • 당신은 4 바이트를 복사하지만 대상은 int을 입력합니다. int은 특정 크기가 보장되지 않으므로 memcpy 일 전에 길이가 4 바이트 이상인지 확인해야합니다.
  • memcpy은 바이트 단위로 작동하지만 정수는 일련의 바이트입니다. 대상 아키텍처에 따라 정수 내의 바이트가 다르게 정렬 될 수 있습니다 (빅 엔디안, 리틀 엔디안 등). 정수에 memcpy을 사용하면 예상 한대로 작동하지 않을 수도 있습니다. memcpy 및 친구들이 어떻게 작동 하는지를 배울 때 바이트 배열을 사용하는 것이 가장 좋습니다.
  • 두 번째 memcpypB+1을 대상으로 사용합니다. 이것은 포인터를 1 바이트 전진시키지 않고 sizeof(*pB) 바이트 씩 진행합니다. 이 경우 잘못된 주소 (변수의 끝을 지나서)를 가리키고 있습니다. memcpy을 호출하면 임의의 메모리가 손상되어 프로그램이 중단되거나 예기치 않은 결과가 발생할 수 있습니다.
+0

나는 많이 배웠다. 나는 한 가지 질문을 가지고있다, 당신은 int가 '4bytes를 차지할 것을 보증하지 않는다고 말한다. 나는 그것이라고 생각했다? 4bytes는 걸릴 수있는 한계입니까? int를 생성하고 값에 intilize 할 때 비트 수 또는 네스 캐리 만 사용합니까? –

+0

int 크기는 기계 및 컴파일러에 따라 다릅니다. 필자는 4 바이트 정수가없는 최신 컴파일러/CPU를 생각할 수는 없지만 많은 오래된 정수를 생각할 수 있습니다. 미래의 기계가 더 큰 int를 가질 가능성이 높습니다. 128 비트 컴퓨터를 사용하면 int는 64 비트 (8 바이트)가됩니다. –

+0

@ user1372122- 기본형'short','int','long' 및'long long'은 표준화 된 크기가 없습니다. 'int'는 * fixed * 크기이지만 고정 크기는 플랫폼에 따라 다릅니다 (예 : x86과 MIPS CPU 사이 또는 32 비트와 64 비트 OS 사이). 그러나 특정 크기를 갖도록 보장 된 데이터 유형이 있습니다. 그것들은'uint32_t'와'int16_t' (각각 32 비트 부호없는 정수와 16 비트 부호있는 정수)와 같은 이름을 가지고 있으며'stdint.h '에서 유래했습니다. – bta

0

pB는 long long * 유형이므로 1을 추가하면 변수 b 뒤에 오는 8 바이트의 다음 세트에 주소가 추가됩니다. pB [0]은 변수 b이지만 pB [1] (pB + 1과 동일)는 정의되지 않은 메모리를 가리 킵니다. 그것에 쓰면 충돌이 발생할 수 있습니다.

long long b[2]; 

(당신이 좋아 초기 값이 무엇이든지 사용)

당신의 cout을 모두 B [0]와 b를 공급해야합니다으로

long long b; 

를 교체 [1]. 코드와

2

나는 memcpy()이 당신이 원하는 것을 위해 디자인되었다고 생각하지 않습니다. 일반적으로, 당신은

int a[4] = { 1, 2, 3, 4 }; 
    int b[3]; 
    int c[5] = { 0 }; 

    ::memcpy(b, a, 3 * sizeof(int)); // b is { 1, 2, 3 } 
    ::memcpy(c+2, b, 3 * sizeof(int)); // c is { 0, 0, 1, 2, 3 } 

C + 2 (객체가 INT, 숯불, 오래 오래, 등 수 있습니다 경우) 하나 이상의 전체 개체를 복사 할 memcpy()을 사용하는 것은 "C + 2 바이트입니다 ". "c + 2 ints"(Win32/x86 시스템에서는 8 바이트)입니다.

은 char 또는 unsigned char 포인터로 캐스팅하여 개별 바이트에 액세스하지만 많은 함정이있는 것을 실제로 이해하지 않는 한 권장하지 않습니다.

unsigned x = 0; 
    unsigned char *px = reinterpret_cast<unsigned char *>(&x); 

    px[0] = 0xFF; 
    px[2] = 0xAA; 

여기서 위험한 점은 컴퓨터가 정수를 저장하는 방법에 대한 지식이 있다고 가정한다는 것입니다. x86 시스템에서 x는 0x00AA00FF이지만 Sun Sparc 시스템에서는 0xFF00AA00입니다.

정수의 일부를 설정해야하는 경우 "or"및 "shift"를 사용하는 것이 더 나을 때가 많습니다.

x = (0xFF<<24) | (0xAA<<8); 

은 모든 아키텍처에서 0xFF00AA00을 제공합니다. 0xFF < < 24는 0xFF를 왼쪽으로 24 비트 시프트하여 0xFF000000이됩니다. 0xAA < < 8 값 0xAA를 왼쪽으로 8 비트 씩 이동하여 0x0000AA00이됩니다.

"또는"함께 0xFF00AA00을 표시합니다.

-1

memcpy는 바이트 단위로 작동하지만 정수는 일련의 바이트입니다.

잘못된 설명.

위의 대답은 strcpy()의 경우 다소 많았지 만 mem_xxx() 함수가 모두 작업 속도를 높이기 위해 memcpy()의 경우 완전히 잘못되었습니다.

  1. 하면 다음 memcpy() 기능이 바이트 단위로 복사를 기반으로 할 것

    경우 ... 기본적으로

    mem_xxx 모든 기능은 다음과 같이 구현 치명적인 느린 것 소스 및/또는 목적지 포인터가 정렬되지 않았다면, 그 함수들은 먼저 정렬되지 않은/홀수 메모리 청크를 처리함으로써 포인터를 정렬합니다.

  2. 다음으로 정렬 된 메모리 영역을 처리하는 데 가장 빠른 아키텍처 종속적 인 방법이 사용됩니다.
  3. 마지막으로 정렬되지 않은/홀수 바이트가 처리됩니다.

나는 실제로 을 추천합니다. 정확하지 않은 답변을 올리기 전에 코드를 읽으십시오.

+0

[이 답변] (https://stackoverflow.com/a/11025101/207421)에 댓글을 달고있는 것 같습니다.그 사실을 분명히해야합니다. 자신의 대답은 SIMD 명령어를 사용할 수있을만큼 최근의 x86을 전제로합니다. – EJP