주인장 보충: 말이 좀 애매하긴 한데, 관련 문서에 있는 aero님의 문서를 참조하면 좀 쉽다. 숫자를 나타내는 c 등에 *가 붙으면, 인자로 주어진 값 리스트의 나머지 원소들을 다 가져와서 pack하게 된다. {{{#!vim perl $a = pack "c*", "65", "66", "67"; # $a = "ABC", 즉 "66","67"을 다 가져왔다 }}} 반면에 스트링을 나타내는 a 같은 경우에는 그 문자에 해당하는 원소의 나머지 문자들 전부를 가져온다. {{{#!vim perl $a = pack "a*", "abc", "def", "ghi"; # $a = "abc", 즉 첫번째 값 "abc"의 나머지 문자인 b와 c를 가져왔다 }}}
주인장의 보충: "Pack / Unpack Tutorial"의 마지막 예제 코드에 있는 DumpString를 사용하여 덤프를 출력하며 비교해보자. * 스트링 데이타를 3개 준비하고 {{{#!vim perl my $str1 = "ABC\x{41}DEFGHI"; # 널 캐릭터 포함해서 10글자짜리 my $str2 = "abc\x{00}defghi"; my $str3 = "123\x{00}567890"; }}} * P코드 뒤에 길이를 붙이며 pack {{{#!vim perl my $pack1 = pack( 'P' , $str1, $str2, $str3 ); my $pack2 = pack( 'P2', $str1, $str2, $str3 ); my $pack3 = pack( 'P*', $str1, $str2, $str3 ); my $pack4 = pack( 'PP', $str1, $str2, $str3 ); my $pack5 = pack( 'P2P3', $str1, $str2, $str3 ); }}} * 덤프를 뜬다 {{{#!vim perl DumpString( $pack1 ); DumpString( $pack2 ); DumpString( $pack3 ); DumpString( $pack4 ); DumpString( $pack5 ); }}} ** 출력은 {{{#!vim 0 048 130 084 009 30 82 54 09 0 T 0 048 130 084 009 30 82 54 09 0 T 0 048 130 084 009 30 82 54 09 0 T 0 048 130 084 009 136 081 084 009 30 82 54 09 88 51 54 09 0 T Q T 0 048 130 084 009 136 081 084 009 30 82 54 09 88 51 54 09 0 T Q T }}} ** 처음 셋은 다 동일하다, 'P'는 해당 변수의 주소를 pack하는 것이라서, "길이"란 게 의미가 없다. ** "PP"로 템플릿을 주었을 때는 $str1과 $str2의 주소가 각각 pack된다. ** "PP"와 "P2P3"도 서로 동일하다. * 이걸 unpack하자. 리스트의 원소들을 구분하기 위해 "|" 기호로 join하고, 좌우에도 대괄호를 붙여서 공백을 확인할 수 있게 한다. {{{#!vim perl print "[", join( '|', unpack( 'P' , $pack1 ) ), "]\n"; # "A" print "[", join( '|', unpack( 'P2' , $pack2 ) ), "]\n"; # "AB" print "[", join( '|', unpack( 'P10', $pack2 ) ), "]\n"; # "ABC\0DEFGHI" print "[", join( '|', unpack( 'P*' , $pack3 ) ), "]\n"; # 런타임에 에러가 난다. print "[", join( '|', unpack( 'PP' , $pack4 ) ), "]\n"; # ( "A", "a" ) print "[", join( '|', unpack( 'P2P3' , $pack4 ) ), "]\n"; # ( "AB", "abc" ) }}} ** 출력은 {{{#!vim [A] [AB] [ABCDEFGHI] 'P' must have an explicit size in unpack at ./t07.pl line 25. <- 실제로는 이 시점에서 에러가 나며 프로그램이 종료되므로, 'P*' 라인을 지워야 이하의 출력이 나온다. [A|a] [AB|abc] }}} ** "P"는 "P1"로 간주되는 걸 알 수있다. ** "P*"는 시작 주소를 주면서 "길이는 최대"라고 주는 셈이라서 의미가 없다. 런타임 에러가 나면서 프로그램이 종료된다. ** "PP"는 pack되어 있던 두 개의 포인터에서 각각 한 바이트씩을 끄집어낸다. ** "P2P3"는 두 개의 포인터에서 2바이트, 3바이트씩 가져온다. * 이번에는 "p"를 사용하여 동일하게 pack {{{#!vim perl my $pack1 = pack( 'p' , $str1, $str2, $str3 ); my $pack2 = pack( 'p2', $str1, $str2, $str3 ); my $pack3 = pack( 'p*', $str1, $str2, $str3 ); my $pack4 = pack( 'pp', $str1, $str2, $str3 ); my $pack5 = pack( 'p2p3', $str1, $str2, $str3 ); }}} * 덤프를 뜬다. {{{#!vim perl DumpString( $pack1 ); DumpString( $pack2 ); DumpString( $pack3 ); DumpString( $pack4 ); DumpString( $pack5 ); }}} ** 출력 {{{#!vim 0 048 130 084 009 30 82 54 09 0 T 0 048 130 084 009 136 081 084 009 30 82 54 09 88 51 54 09 0 T Q T 0 048 130 084 009 136 081 084 009 176 223 084 009 30 82 54 09 88 51 54 09 b0 df 54 09 0 T Q T T 0 048 130 084 009 136 081 084 009 30 82 54 09 88 51 54 09 0 T Q T 0 048 130 084 009 136 081 084 009 176 223 084 009 232 074 083 009 30 82 54 09 88 51 54 09 b0 df 54 09 e8 4a 53 09 0 T Q T T J S 16 232 074 083 009 e8 4a 53 09 J S }}} ** 'p'는 $str1의 포인터를 pack ** 'p2'는 'p'와 다르다. $str1, $str2의 포인터를 pack한다 ** 'p*'는 뒤에 오는 리스트 전부를 받아들이니 총 3개의 포인터 ** 'pp'는 'p2'와 같다 ** 'p2p3'는 좀 묘하다. 'ppppp'와 같은 상황이니 변수 3개의 포인터가 앞에 pack되는 데, 그 뒤에 8바이트가 더 있다. 포인터 두개가 더 들어가 있는 듯 한데, 둘은 같은 값이다. * unpack해보자. {{{#!vim perl print "[", join( '|', unpack( 'p' , $pack1 ) ), "]\n"; print "[", join( '|', unpack( 'p2' , $pack2 ) ), "]\n"; print "[", join( '|', unpack( 'p10', $pack2 ) ), "]\n"; print "[", join( '|', unpack( 'p*' , $pack3 ) ), "]\n"; print "[", join( '|', unpack( 'pp' , $pack4 ) ), "]\n"; print "[", join( '|', unpack( 'p2p3' , $pack5 ) ), "]\n"; }}} ** 출력 {{{#!vim [ABC] [ABC|abc] [ABC|abc] [ABC|abc|123] [ABC|abc] [ABC|abc|123||] }}} ** 'p'는 길이가 명시되지 않아서 널 캐릭터가 있는 곳까지 세 글자를 가져온다. ** 'p2'는 포인터 두개에서 세 글자를 가져온다. ** 'p10'을 해봤자 실제 pack되어 있는 포인터는 두개뿐이니 'p2'와 같은 출력 ** 'p*'는 pack되어 있는 모든 포인터에서 스트링을 가져온다. ** 'pp'는 'p2'와 같다 ** 'p2p3'는 'ppppp'와 같고, 처음 세 포인터에서 세 글자씩 가져오고, 나머지 두 포인터를 가지고도 unpack하여 원소가 두 개 더 반환되었다. 실제로 뭐를 가리키는지 몰라도, 아무것도 출력되지 않았다.
주인장 보충: 위 예 중에 {{{#!vim perl # 시스템 고유의 integer 타입이 몇 비트를 차지하는지 검사 $bits = unpack( '%32I!', ~0 ); }}} 이것은 제대로 동작하지 않는다(적어도 주인장이 테스트한 Perl 5.8.8에서는 그랬다). 아래처럼 바꿔야 한다. {{{#!vim perl $bits = unpack( '%32B*', pack( 'I!', ~0 ) ); }}}