굉장히 중요한 개념이다 !!!
저장소 배열의 선언과 입력
배열이 어디에 저장되는지에 따라
메모리 배열
과 저장소 배열
로 나눌 수 있다.
메모리
에 저장된 데이터는
컨트랙트의 실행이 종료되면 지워진다.
하지만 저장소
에 저장된 데이터는
블록체인
에 저장
되어
실행이 종료되어도 영구히 저장된다.
그러므로 다음 실행 시에도
이전에 저장소에 저장한 값을 사용할 수 있다.
다만 저장소보다
메모리에 저장하는 것이 gas 소모량이 적다.
상태 변수
는 무조건 저장소
에 저장이 되며,
지역 변수
는 옵션에 따라
저장소
와 메모리
를 변경할 수 있다.
하지만 기본적
으로는 저장소
에 저장되므로
별도로 memory 키워드를 붙이지 않으면
저장소 배열로 선언된다.
아래의 예제에서 선언된 배열들(좌변)은 모두 저장소 배열
이다.
반면에 입력값
이나 new 키워드
로 선언되는 배열들(우변)은
임시로 메모리에 저장되는 메모리 배열
이다.
1 pragma solidity ^0.4.8;
2
3 contract Example4 {
4 uint32[32] globalStaticArray = [1, 2, 3];
5 uint8[] globalDinamicallyArray = new uint8[](7);
6 uint8[3] globalErrorArray = [ 1234, 3456, 5678 ]; // [1]
7
8 function arrayExample( ) {
9 uint8[3] localStaticArray = [1234, 3456, 5678]; // [2]
10 uint8[3] localErrorArray = new uint8[] (localStaticArray.length); // [3]
11 uint8[] localDinamicallyArray = globalDinamicallyArray;
12 }
13 }
[1],[2],[3]에서 오류가 발생한다.
메모리 배열을 상태 배열에 대입할 때(4, 5행),
배열이 복사되어 사본이 대입된다.
하지만 매모리 배열을 지역 배열에 대입할 수 없으므로
컴파일 오류가 발생한다.(9, 10행)
지역 배열은 11행과 같이
다른 저장소 배열을 참조 or memroy 배열로 선언하여 사용하여야한다.
배열이 상태 배열로 대입될 때에는
사본이 복사되면서 필요에 따라 암묵적 형 변환이 일어난다.
예를 들어 예제의 4행에서
우변의 배열([1,2,3])은 unit8[3]의 배열인데,
더 큰 범위를 지원하는 uint32[3]의 배열 globalStaticArray에 대입될 때
암묵적으로 형 변환이 된다.
반면 6행에서 우변([1234,3456,5678])은 uint16[3] 배열로,
더 작은 uint8[3]의 배열 globalErrorArray로
암묵적 형 변환이 불가능하여 오류가 발생한다.
이 때는 더 큰 범위의 배열로 바꾸거나 or 데이터 손실을 감안한
명시적 형변환이 필요하다.
uint256[3] globalErrorArray = [ 1234, 3456, 5678 ];
이렇게 변경하면 컴파일오류가 나지 않는다.
메모리 배열의 선언과 입력
앞서 지역 배열의 경우
기본적으로 선언과 동시에 값을 입력할 수 없다고 했다.
하지만 메모리 배열
은
new 키워드를 사용 or 원소들을 대괄호를 묶어서 할당이 가능하다.
(위의 예제)9,10행을 메모리 배열로 선언하고,
10행은 동적 배열로 수정하면 컴파일 오류가 해결된다.
메모리 배열
은 저장소 배열과 다르게
암묵적인 형 변환
을 지원하지 않는다.
그러므로 9행에서 좌변을 uint256[3]이 아닌 다른 크기로 변경하면
오류가 발생한다.
마지막으로 기본적으로 동적 배열
의 길이는
실행 중에도 결정할 수 있지만,
메모리 동적 배열
은 저장소 동적 배열과는 다르게
한 번 생성된 후에는 length에 값을 입력함으로써
배열의 길이를 바꿀 수 없다.