2016-05-31 2 views
1

아래의 예에서 궁금한 점은 line 17이 작동하지 않는 이유는 무엇입니까? line 18? System.AddressInteger (line 17 참조)로 직접 변환 할 수 있습니까?Ada의 System.Address에서 Integer로 변환

main.adb

with Ada.Text_IO; 
with Ada.Unchecked_Conversion; 
with System.Storage_Elements; 

procedure Main is 
    package SSE renames System.Storage_Elements; 

    type Integer_Access is access Integer; 
    I1_Access : Integer_Access := new Integer'(42); 
    I1_Address : System.Address := I1_Access.all'Address; 

    function Convert1 is new Ada.Unchecked_Conversion (System.Address, Integer); 
    function Convert2 is new Ada.Unchecked_Conversion (System.Address, Integer_Access); 
begin 
    Ada.Text_IO.Put_Line (SSE.To_Integer (I1_Access'Address)'Img); 
    Ada.Text_IO.Put_Line (SSE.To_Integer (I1_Access.all'Address)'Img); 
    Ada.Text_IO.Put_Line (I1_Access.all'Img); 
    Ada.Text_IO.Put_Line (Convert1 (I1_Address)'Img); -- why does this NOT work? 
    Ada.Text_IO.Put_Line (Convert2 (I1_Address).all'Img); -- why does this work? 
end Main; 

결과

140734773254664 
140243203260416 
42 
-363855872 
42 

답변

6

12. function Convert1 is new Ada.Unchecked_Conversion (System.Address, Integer); 
     | 
    >>> warning: types for unchecked conversion have different sizes 

Integer 때문에 32 비트 나는 (발췌) 수 (목록을 생성) System.Address (대부분의 액세스 동안 유형)은 64 비트입니다. 귀하의 기계는 분명히 유사합니다.

이상한 5 번째 출력 라인을 얻는 이유는 (실제로는 -490720512가 있습니다.) 실제 주소의 아래쪽 32 비트만을보고있는 것입니다.

지원되는 방법은 System.Address_To_Access_Conversions (ARM 13.7.2)입니다.

+0

감사! 나는'Convert3 is new System.Address_To_Access_Conversions (Integer);와'Ada.Text_IO.Put_Line (Convert3.To_Pointer (I1_Address) .all'Img); '가 작동하는 패키지를 시도했다. 이제 Convert1이 작동하지 않는 이유도 있습니다. – user1091344

3

그것은 작업을 수행합니다. 분명히 그것은 당신이 예상했던 것 이외의 것을하고있는 것 같습니다.

System.AddressInteger으로 변환하면 Unchecked_Conversion이지만 결과가 의미있는 것은 아닙니다. System.Address 값에 보관 된 (아마도 가상의) 주소를 나타내는 정수 -이 아닌이 가리키는 모든 객체의 값을 가져옵니다. System.AddressInteger이 같은 크기가 아니라면 그 결과는 의미가별로 없습니다.

Ada.Text_IO.Put_Line (Convert1 (I1_Address)'Img); 

이것은 메모리 주소의 표현을 Integer으로 인쇄합니다. 특히 의미있는 것은 아닙니다. (일반적으로는 16 진수로 같은 주소를 참조 할 것.)

Ada.Text_IO.Put_Line (Convert2 (I1_Address).all'Img); 

I1_Address의 값이 나타내는 메모리 위치에있는 객체의, 42Integer 값을 출력합니다. 이것은 단지 원형의 인쇄 방법입니다. I1_Access.all. 나는 당신의 -gnatwa이 맥 코드 (대부분의 경고) 및 -gnatl를 컴파일 할 경우

+0

고마워요! 그래서, System.Address 뒤에 값을 가져 오는 정확한 방법은'System.Address'를'Integer' 액세스 타입으로 변환 한 후 역 참조하는 것입니다 - 제가 18 행에서하고있는 것처럼? – user1091344

+0

@ user1091344 :이 경우 이미'Integer_Access' 값을 가지고 있습니다.이 값은'System.Address'로 변환하고 다시 돌아옵니다. 그러나 만약 당신이 어떤 외부 소스로부터'System.Address' 값을 가지고 있고 그것이 가리키는'Integer' 객체에 접근해야한다면'Unchecked_Conversion'을 수행하여'access integerer' 유형으로 변환해야합니다 당신은 역 참조 할 수 있습니다. ('System.Address' 값이 유효하지 않으면, 이것은 당신의 얼굴에서 날아갈 수 있습니다.)하지만 실제로 필요하지 않는 한 그렇게하지 마십시오. (더 깨끗한 접근법이있을 수 있으며, 저는 Ada에서 꽤 오랫동안 떨어져있었습니다.) –

+1

@KeithThompson'System.Address'와 접근 유형을 변환하기 위해'Unchecked_Conversion'을 사용하는 것은 신뢰할 만합니다. 비 GNAT 컴파일러의 경우, 액세스 유형은 경우에 따라 주소 외에 추가 데이터 (예 : 배열 범위, 액세스 가능성 수준, 스택 프레임 포인터)를 포함하는 "뚱뚱한"포인터 일 수 있습니다. 'System.Address_To_Access_Conversions'가 더 안정적입니다. – ajb

3

예에서와 같이 이미지의 값만 인쇄하려면 System.Address_Image 함수를 사용하는 것이 좋습니다. 이것은 포인터 연산에는 좋지 않지만 더 나은 출력 (예 : 16 진수)을 유도합니다.