C \ # 데이터 구조 - Array. Copy 와 Buffer. BlockCopy 상세 설명
9600 단어 C#데이터 구조 와 알고리즘Array.Copy
1. Array. copy 의 자세 한 문서
주어진 색인 부터 배열 의 일련의 요 소 를 복사 하여 다른 배열 에 붙 여 넣 습 니 다 (주어진 색인 부터 복사 하 는 색인 시작)
문법
public static void Copy(
Array sourceArray,
long sourceIndex,
Array destinationArray,
long destinationIndex,
long length
)
매개 변수
sourceArray
유형: System. Array
복사 할 데 이 터 를 포함 하 는 배열 입 니 다.
sourceIndex
형식: System. Int 64
복사 시작 시 sourceArray 의 색인 을 표시 하 는 64 비트 정수
destinationArray
유형: System. Array
데 이 터 를 받 는 배열.
destinationIndex
형식: System. Int 64
시작 한 destinationArray 의 색인 을 저장 하 는 64 비트 정수
length
형식: System. Int 64
복사 할 요소 수 를 나타 내 는 64 비트 정수정 수 는 0 과 Int 32 사이 에 있어 야 합 니 다.MaxValue, 포함.
비고
이 sourceArray 와 destinationArray 인 자 는 같은 차원 을 가 져 야 합 니 다.또한 destinationArray 는 복사 한 데 이 터 를 수용 할 수 있 도록 사 이 즈 를 표시 하고 destinationIndex 위치 에서 시작 하 는 요 소 를 충분히 가 져 야 합 니 다.
다 차원 배열 간 에 복 제 를 할 때 배열 의 조작 은 마치 긴 1 차원 배열 과 같 습 니 다. 그 중에서 줄 (또는 열) 은 개념 적 으로 단 대 단 에 놓 여 있 습 니 다.예 를 들 어 한 배열 에 세 줄 (또는 열) 이 있 으 면 줄 마다 네 개의 요소 가 있 고 배열 의 시작 부분 에서 여섯 개의 요 소 를 복사 하면 첫 번 째 줄 (또는 열) 의 모든 네 개의 요소 와 두 번 째 줄 의 앞 두 개의 요소 (또는 열) 를 복사 합 니 다.세 번 째 줄 (또는 열) 의 두 번 째 요 소 를 복사 하려 면 sourceIndex 는 첫 번 째 줄 (또는 열) 의 상한 선 에 두 번 째 줄 (또는 열) 의 길 이 를 두 개 더 해 야 합 니 다.
sourceArray 와 destinationArray 가 겹 치면 이 방법 은 destinationArray 를 덮어 쓰기 전에 sourceArray 의 원본 값 이 임시 위치 에 저 장 된 것 과 같 습 니 다.
[C / C ++]
이 방법 은 memcpy 가 아 닌 표준 C / C + 함수 memmove 에 해당 합 니 다.
memmove 와 memcpy 의 차이
memcpy () 와 memmove () 는 모두 C 언어의 라 이브 러 리 함수 로 헤더 파일 string. h 에서 일정한 길이 의 메모리 내용 을 복사 하 는 역할 을 합 니 다.원형 은 다음 과 같다.
void *memcpy(void *dst, const void *src, size_t count);
void *memmove(void *dst, const void *src, size_t count);
그들의 역할 은 똑 같 습 니 다. 유일한 차이 점 은 메모리 가 부분 적 으로 중첩 되 었 을 때 memmove 는 복사 결과 가 정확 하고 memcpy 는 복사 결과 가 정확 하 다 는 것 을 보증 하지 않 습 니 다.
메모리 덮어 쓰기 상황 은 다음 과 같은 두 가지 가 있 습 니 다.
memcpy () 와 memmove () 두 함수 의 실현:
void* my_memcpy(void* dst, const void* src, size_t n)
{
Assert(dst != null && src != null);
char *tmp = (char*)dst;
char *s_src = (char*)src;
while(n--) {
*tmp++ = *s_src++;
}
return dst;
}
이 를 통 해 알 수 있 듯 이 memcpy () 는 메모리 왼쪽 에 있 는 한 바이트 에서 src 의 내용 을 dst 메모리 에 복사 하 는 것 입 니 다. 이러한 실현 방식 은 그림 의 두 번 째 메모리 가 겹 치 는 상황 에서 마지막 두 바이트 의 복사 값 은 원래 의 값 이 아 닙 니 다. 새로운 값 은 src 의 최초 2 바이트 가 되 었 습 니 다.
한편, memmove 는 두 번 째 메모리 커버 상황 에 대해 memcpy 를 개선 한 것 입 니 다. 개선 코드 는 다음 과 같 습 니 다.
void* my_memmove(void* dst, const void* src, size_t n)
{
Assert(dst != null && src != null);
char* s_dst;
char* s_src;
s_dst = (char*)dst;
s_src = (char*)src;
if(s_dst > s_src && (s_src + n > s_dst)) { // 。
s_dst = s_dst+n-1;
s_src = s_src+n-1;
while(n--) {
*s_dst-- = *s_src--;
}
}else {
while(n--) {
*s_dst++ = *s_src++;
}
}
return dst;
}
배열 은 형식 배열 이나 값 형식 배열 을 참조 하여 필요 한 실행 유형 에 따라 아래로 전환 할 수 있 습 니 다.
참조 형식 배열 에서 값 형식 배열 로 복사 할 때 모든 요 소 는 상 자 를 뜯 어 복사 합 니 다.값 형식 배열 에서 참조 형식 배열 로 복사 할 때 모든 요 소 는 포장 되 고 복 사 됩 니 다.
인용 형식 이나 값 형식 배열 에서 Object 배열 로 복사 할 때 각각 값 이나 인용 을 저장 하기 위해 Object 를 만 들 고 복사 합 니 다.Object 배열 에서 인용 형식 이나 값 형식 배열 로 복사 하 는 것 은 할당 이 불가능 합 니 다. InvalidCastException 을 던 집 니 다.
sourceArray 와 destinationArray 가 모두 인용 형식의 배열 이거 나 Object 형식의 배열 이 라면 얕 은 복사 가 실 행 됩 니 다.Array 의 얕 은 복사 본 은 원본 Array 의 같은 요소 에 대한 인용 을 포함 하 는 새로운 Array 입 니 다.요소 자체 나 요소 가 인용 한 모든 내용 은 복사 되 지 않 습 니 다.이에 비해 Array 의 심층 복사 본 은 요소 가 직접적 이거 나 간접 적 으로 인용 한 요소 와 모든 내용 을 복사 합 니 다.
예시
int count = 10000;
int[,] arr1 = new int[count, count];
for (int i = 0; i < count; i++)
{
for (int j = 0; j < count; j++)
{
arr1[i, j] = i;
}
}
int[,] arr2 = new int[count, count];
Array.Copy(arr1, 0, arr1, 1000, count);
2. Buffer. BlockCopy 의 상세 한 문서
문법
지정 한 오프셋 에서 시 작 된 원본 배열 에서 지정 한 수량의 바이트 를 특정 오프셋 으로 시작 하 는 대상 배열 로 복사 합 니 다.
public static void BlockCopy(
Array src,
int srcOffset,
Array dst,
int dstOffset,
int count
)
매개 변수
src
유형: System. Array
소스 버퍼.
srcOffset
형식: System. Int 32
0 기반 바이트 가 src 로 이동 합 니 다.
dst
유형: System. Array
대상 버퍼.
dstOffset
형식: System. Int 32
0 기반 바이트 가 dst 로 이동 합 니 다.
count
형식: System. Int 32
복사 할 바이트 수 입 니 다.
비고
이 방법 은 src 에서 src Offset 색인 부터 count 바이트 를 복사 하고 dst 의 색인 dst Offset 부터 dst 로 복사 합 니 다.src Offset 과 dst Offset 은 모두 0 에서 시 작 됩 니 다. 각 버퍼 의 첫 번 째 바이트 가 위치 1 이 아 닌 위치 0 에 있다 는 것 이다.
... 해 야 한다 BlockCopy 방법 으로 접근 하 는 바이트 의 src 는 색인 이나 상부, 하부 배열 경계 파라미터 배열 등 프로그램 구조 가 아 닌 메모리 에서 의 오프셋 을 사용 합 니 다.예 를 들 어 응용 프로그램의 프로 그래 밍 언어 에서 Int 32 배열 을 설명 하면 하한 선 은 - 50 이 고 이 배열 과 오프셋 5 를 BlockCopy 방법 에 전달 합 니 다. 이 방법 은 첫 번 째 배열 요 소 는 배열 의 두 번 째 요소 로 색인 - 49 곳 에 있 습 니 다.또한, 먼저 배열 요소 - 49 색인 에 접근 하 는 바이트 는 프로그램 을 실행 하 는 컴퓨터 바이트 순서 에 달 려 있 습 니 다.
말 그대로 BlockCopy 방법 은 바이트 블록 을 한 번 에 복사 하 는 것 이 아니 라 전체 로 복사 합 니 다.따라서 src 와 dst 가 같은 배열 을 인용 할 때 src Offset + count -1 의 범위 와 dst Offset + count -1 범위 가 겹 치면 겹 치 는 바이트 의 값 은 대상 으로 복사 되 기 전에 덮어 쓰 지 않 습 니 다.
예시
다음 예제 에서 arr 라 는 배열 의 바이트 0 - 16 값 은 바이트 12 - 28 로 복사 되 었 습 니 다.범위 가 겹 쳤 음 에 도 불구 하고 원본 바이트 의 값 은 성공 적 으로 복사 되 었 습 니 다.
const int INT_SIZE = 4;
int[] arr = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
Buffer.BlockCopy(arr, 0 * INT_SIZE, arr, 3 * INT_SIZE, 4 * INT_SIZE);
foreach (int value in arr)
Console.Write("{0} ", value);
// The example displays the following output:
// 2 4 6 2 4 6 8 16 18 20
테스트
1.1 다 차원 배열 에 대한 성능 테스트
테스트 데이터 int [,] arr1 = new int [10000, 10000];모든 데이터 복사
Array. Copy () 실행 결과: ElapsedTicks
Buffer. BlockCopy () 실행 결과: ElapsedTicks
같은 배열 의 복사 가 중첩 되 어 있다.
1359136
1250880
같은 배열 의 복사 가 겹 치지 않 습 니 다.
1420934
1306125
다른 배열
1397174
1345293
그리고 여러 번 의 테스트 를 통 해 Buffer. BlockCopy () 의 실행 효율 은 Array. copy () 보다 좋 습 니 다.
1.2 1 차원 배열 에 대한 성능 테스트
테스트 데이터 200 MB int [], 한 번 에 100 MB 복사
Array. Copy () 실행 결과: ElapsedTicks
Buffer. BlockCopy () 실행 결과: ElapsedTicks
같은 배열 의 복사 가 중첩 되 어 있다.
431120
426114
같은 배열 의 복사 가 겹 치지 않 습 니 다.
421117
421088
다른 배열
421083
421134
다시 말 하면 Buffer. BlockCopy () 의 실행 효율 은 Array. copy () 와 거의 유사 하 다.
4. 난 발 정
위의 성능 테스트, Buffer. BlockCopy (arr, offset, arr 1, offset 1, count) 의 offset, offset 1 과 count 는 모두 바이트 가 메모리 에서 편 이 량 이 고, offset, offset 1 은 그룹 인덱스 가 아니 며, count 도 그룹의 데이터 길이 가 아니다.
처음 시 작 된 다 차원 배열 과 1 차원 배열 의 복사 테스트 에서 배열 의 데이터 길 이 를 직접 매개 변수 로 전송 하고 Buffer. BlockCopy () 의 실행 효율 은 Array. copy () 보다 훨씬 좋 으 며 특히 1 차원 배열 의 복사 테스트 에서 약 4 배의 장점 이 있다.사실 이러한 테스트 는 버 퍼 블록 복사 (Buffer. BlockCopy) 방법 이 데 이 터 를 모두 복사 하지 않 고 1 / 4 만 복사 해 이렇게 큰 차이 가 생 겼 다.
Buffer. BlockCopy () 에 들 어 오 는 count 는 배열 의 데이터 길 이 를 4 로 곱 해 야 합 니 다. int 가 4 개의 바이트 를 차지 하기 때문에 count 는 메모리 에서 바이트 의 오프셋 을 대표 합 니 다.정확 한 count 가 들 어 온 후에 1 차원 배열 복사 테스트 는 이들 의 성능 에 차이 가 거의 없다.다 차원 배열 의 복사 테스트 는 어느 정도 차이 가 있 습 니 다. Buffer. BlockCopy () 의 실행 효율 은 Array. copy () 보다 좋 습 니 다.
말 그대로 Buffer. BlockCopy () 의 실행 효율 은 Array. Copy () 보다 좋 습 니 다. 왜 Array. Copy () 인터페이스 가 존재 합 니까?
Buffer. BlockCopy () 가 배열 요소 색인 에 접근 하 는 바 이 트 는 프로그램 을 실행 하 는 컴퓨터 바이트 순서 에 달 려 있 기 때 문 입 니 다.
컴퓨터 하드웨어 는 두 가지 데 이 터 를 저장 하 는 방식 이 있 습 니 다. 큰 바이트 순서 (big endian) 와 작은 바이트 순서 (little endian) 입 니 다.
예 를 들 어 16 진수 0x 0102, 16 진법 은 모든 숫자 가 4bit 를 차지 하고 네 개의 숫자 16bit, 즉 2byte, 2 개의 바이트 저장 소 를 차지한다.0x 0102 고위 바이트 는 0x 01 이 고 낮은 바이트 는 0x 02 이다.
l 큰 바이트 순서: 높 은 바이트 가 앞 에 있 고 낮은 바이트 가 뒤에 있 습 니 다. 이것 은 인류 가 수 치 를 읽 고 쓰 는 방법 입 니 다.
메모리 주소
0x100
0x101
대 단자 바이트 순서
01
02
l 작은 바이트 순서: 낮은 바이트 가 앞 에 있 고 높 은 바이트 가 뒤에 있 습 니 다.
메모리 주소
0x100
0x101
작은 바이트 순서
02
01
따라서 큰 바이트 순서 와 작은 바이트 순서 가 다른 컴퓨터 장치 에서 Buffer. BlockCopy () 가 복사 한 데 이 터 는 다 르 고 큰 바이트 순서 장치 에서 복사 한 데 이 터 는 0x 0102 이다.작은 바이트 순서 장치 에서 복사 한 데 이 터 는 0x 0201 이기 때문에 Array. copy () 인터페이스 에 존재 하 는 의 미 는 바로 여기에 있 습 니 다.
다음 의 예 를 보 세 요. 한 바이트 의 길이 만 복사 하고 arr 1 배열 에 복사 할 때 윈도 우 는 작은 바이트 순 서 를 기반 으로 하기 때문에 0x 02 에서 arr [0] 의 첫 번 째 오프셋 위치 만 복사 합 니 다.
아래 의 네 칸 은 int 를 대표 하 는 네 개의 바이트 이다.
arr[0]
02
01
0
0
Arr1[0]
0
02
0
0
arr1 [0] 의 값 은 0x 0200 이 고 10 진법 으로 바 뀌 면 512 이다.
static void Main(string[] args)
{
int[] arr = new int[10];
int[] _arr1 = new int[10];
arr[0] = 0x0102;// 258
// count
Buffer.BlockCopy(arr, 0, _arr1, 1, 1);
Console.WriteLine(arr[0]);// 258
Console.WriteLine(_arr1[0]);// 512
}
따라서 배열 에 잘못 들 어 오 는 데이터 길이 가 있 으 면 데이터 가 완전 하 게 복사 되 지 않 을 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.