Gidhub BE Developer

배열 - (2) (중요)

2018-02-26
goodGid

굉장히 중요한 개념이다 !!!

저장소 배열의 선언과 입력

배열이 어디에 저장되는지에 따라

메모리 배열저장소 배열로 나눌 수 있다.

메모리에 저장된 데이터는

컨트랙트의 실행이 종료되면 지워진다.

하지만 저장소에 저장된 데이터는

블록체인저장되어

실행이 종료되어도 영구히 저장된다.

그러므로 다음 실행 시에도

이전에 저장소에 저장한 값을 사용할 수 있다.

다만 저장소보다

메모리에 저장하는 것이 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에 값을 입력함으로써

배열의 길이를 바꿀 수 없다.


Comments

Content