비트 시프트 (비트 시프트) 연산자 란 무엇이며 어떻게 작동합니까?


1382

여가 시간에 C를 배우려고했지만 다른 언어 (C #, Java 등)는 동일한 개념 (그리고 종종 동일한 연산자)을 가지고 있습니다 ...

핵심 수준에서, 내가 궁금하다, 무슨 않는 비트 이동 ( <<, >>, >>>) 수행이 해결 할 수있는 문제 및 개는이 벤드 주위에 숨어 무엇? 다시 말해, 모든 선의의 비트 이동에 대한 절대 초보자 안내서입니다.


2
3GL에서 비트 시프 팅을 사용하는 기능적 또는 비 기능적 사례는 거의 없습니다.
Troy DeMonbreun

15
이 답변을 읽은 후 다음 링크를 볼 수 있습니다. graphics.stanford.edu/~seander/bithacks.html & jjj.de/bitwizardry/bitwizardrypage.html
발톱

1
비트 시프 팅은 컴퓨터가 매우 쉽고 빠르다는 점에 유의해야합니다. 프로그램에서 비트 시프 팅을 사용하는 방법을 찾으면 메모리 사용 및 실행 시간을 크게 줄일 수 있습니다.
Hoytman

@Hoytman : 그러나 훌륭한 컴파일러는 이러한 많은 트릭을 이미 알고 있으며 일반적으로 의미가있는 곳을 인식하는 것이 좋습니다.
Sebastian Mach

답변:


1713

비트 시프 팅 연산자는 이름에서 의미하는 바를 정확하게 수행합니다. 그들은 비트를 이동시킵니다. 다음은 다양한 변속 연산자에 대한 간략한 소개입니다.

연산자

  • >> 산술 (또는 부호있는) 오른쪽 시프트 연산자입니다.
  • >>> 논리적 인 (또는 부호없는) 오른쪽 시프트 연산자입니다.
  • << 왼쪽 시프트 연산자이며 논리 및 산술 시프트의 요구를 모두 충족시킵니다.

이러한 연산자의 모든 정수 값에 적용 할 수 있습니다 ( int, long, 가능성 shortbytechar). 일부 언어에서는 시프트 연산자를 데이터 유형보다 작은 데이터 유형에 적용 int하면 피연산자의 크기 가 자동으로 조정됩니다 int.

참고 <<<가 중복 될 것이기 때문에, 운영자가 아닙니다.

또한 C와 C ++는 올바른 시프트 연산자를 구분하지 않습니다 . >>연산자 만 제공 하며 올바른 이동 동작은 서명 된 유형에 대해 정의 된 구현입니다. 나머지 답변은 C # / Java 연산자를 사용합니다.

(GCC와 연타 / LLVM을 포함한 모든 주류 C 및 C ++ 구현에서 >>. 서명 유형에 일부 코드는 다음을 가정 연산이지만, 뭔가 표준 보증을하지 않습니다 그것은 아닙니다. 정의되지 않은 ,하지만, 표준이 하나를 정의하는 구현을 필요로 그러나 음수 부호가있는 숫자의 왼쪽 이동 정의되지 않은 동작 (부호가있는 정수 오버플로)이므로 산술 오른쪽 이동이 필요하지 않은 경우 일반적으로 부호없는 유형으로 비트 이동을 수행하는 것이 좋습니다.)


왼쪽 시프트 (<<)

정수는 일련의 비트로 메모리에 저장됩니다. 예를 들어 32 비트로 저장된 숫자 6 int은 다음과 같습니다.

00000000 00000000 00000000 00000110

이 비트 패턴을 왼쪽으로 한 위치 ( 6 << 1)로 이동하면 숫자 12가됩니다.

00000000 00000000 00000000 00001100

보시다시피 숫자는 한 위치 씩 왼쪽으로 이동했으며 오른쪽의 마지막 숫자는 0으로 채워집니다. 또한 왼쪽으로 이동하여 2. 지금의 힘에 의해 곱셈에 해당주의 수도 6 << 1에 해당 6 * 2하고, 6 << 3동일합니다 6 * 8. 좋은 최적화 컴파일러는 가능하면 곱셈을 시프트로 대체합니다.

비 원형 변속

이들은 원형 교대 가 아닙니다 . 이 값을 왼쪽으로 한 위치 이동 ( 3,758,096,384 << 1) :

11100000 00000000 00000000 00000000

3,221,225,472의 결과 :

11000000 00000000 00000000 00000000

"끝에서 벗어난"숫자는 사라집니다. 감싸지 않습니다.


논리 오른쪽 시프트 (>>>)

논리적 오른쪽 시프트는 왼쪽 시프트와 반대입니다. 비트를 왼쪽으로 이동하지 않고 단순히 오른쪽으로 이동합니다. 예를 들어 숫자 12를 이동하면 :

00000000 00000000 00000000 00001100

오른쪽으로 한 위치 ( 12 >>> 1)만큼 원래 6을 다시 가져옵니다.

00000000 00000000 00000000 00000110

따라서 오른쪽으로 이동하는 것은 2의 거듭 제곱으로 나누는 것과 같습니다.

잃어버린 비트가 사라졌습니다

그러나 시프트는 "손실 된"비트를 회수 할 수 없습니다. 예를 들어,이 패턴을 이동 시키면 :

00111000 00000000 00000000 00000110

왼쪽의 4 개의 위치 ( 939,524,102 << 4)에 2,147,483,744를 얻습니다.

10000000 00000000 00000000 01100000

( (939,524,102 << 4) >>> 4) 뒤로 이동 하면 134,217,734가됩니다.

00001000 00000000 00000000 00000110

비트가 손실되면 원래 값으로 되돌릴 수 없습니다.


산술 오른쪽 시프트 (>>)

산술 오른쪽 이동은 논리 오른쪽 이동과 동일하지만 0으로 채워지는 대신 가장 중요한 비트로 채워집니다. 가장 중요한 비트가 부호 비트이거나 양수와 음수를 구별하는 비트 이기 때문 입니다. 가장 중요한 비트로 패딩함으로써 산술 오른쪽 이동은 부호 보존입니다.

예를 들어이 비트 패턴을 음수로 해석하면

10000000 00000000 00000000 01100000

숫자는 -2,147,483,552입니다. 산술 시프트 (-2,147,483,552 >> 4)로 이것을 오른쪽 4 위치로 옮기면 다음과 같이됩니다.

11111000 00000000 00000000 00000110

또는 숫자 -134,217,722입니다.

따라서 우리는 논리적 인 오른쪽 이동이 아닌 산술 오른쪽 이동을 사용하여 음수 부호를 보존했습니다. 그리고 다시 한번, 우리는 2의 거듭 제곱으로 나눗셈을하고 있음을 알 수 있습니다.


304
대답은 이것이 Java 고유의 ​​대답이라는 것을 더 명확하게해야합니다. >>> C / C ++ 또는 C # 및 >> 여부에 운영자가 기호는 C / C ++ (주요 잠재적 잡았다)에서 구현을 정의 전파 전혀 없다
마이클 버

56
C 언어의 맥락에서 대답은 완전히 틀립니다. C에서는 "산술"과 "논리적"시프트로 의미있는 구분이 없습니다. C에서는 시프트가 부호없는 값과 양의 부호있는 값에서 예상대로 작동합니다. 비트 만 이동합니다. 음수 값에서 오른쪽 이동은 구현이 정의되어 있으며 (즉, 일반적으로 수행하는 작업에 대해 아무 것도 말할 수 없음) 왼쪽 이동은 단순히 금지되어 있습니다. 정의되지 않은 동작이 발생합니다.
AnT

10
오드리, 분명히 산술과 논리적 인 오른쪽 이동 사이에는 차이가 있습니다. C는 단순히 선택 구현을 정의 된 상태로 둡니다. 그리고 음수 값에 대한 왼쪽 이동은 확실히 금지되지 않습니다. 왼쪽의 1 비트로 0xff000000을 이동하면 0xfe000000이됩니다.
Derek Park

16
A good optimizing compiler will substitute shifts for multiplications when possible. 뭐? 그것은 CPU의 낮은 수준의 운영에 내려 올 때 Bitshifts이 수십 배 더 빠르다는 할 것 컴파일러를 최적화하는 좋은 정확한 비트 교대로 두의 힘에 의해 보통의 곱셈을 돌려이다 반대.
Mahn

55
@Mahn, 당신은 내 의도에서 거꾸로 읽고 있습니다. X를 Y로 대체한다는 것은 X를 Y로 대체하는 것을 의미합니다. Y는 X를 대체합니다. 따라서 시프트는 곱셈을 대체합니다.
Derek Park

209

단일 바이트가 있다고 가정 해 봅시다.

0110110

하나의 왼쪽 비트 시프트를 적용하면 다음과 같이됩니다.

1101100

가장 왼쪽에있는 0은 바이트에서 벗어나고 바이트의 오른쪽 끝에 새로운 0이 추가되었습니다.

비트는 롤오버되지 않습니다. 그들은 버려집니다. 즉, 1101100을 왼쪽으로 옮긴 다음 오른쪽으로 옮길 경우 동일한 결과를 얻지 못합니다.

왼쪽으로 N만큼 이동하면 2N 으로 곱하는 것과 같습니다 .

N만큼 오른쪽으로 이동하면 ( 1의 보수를 사용 하는 경우 )는 2N 으로 나누고 반올림 하는 것과 같습니다 .

비트 쉬프팅은 2의 거듭 제곱으로 작업하는 경우, 매우 빠른 곱셈과 나눗셈에 사용할 수 있습니다. 거의 모든 저수준 그래픽 루틴은 비트 쉬프팅을 사용합니다.

예를 들어 옛날에는 게임에 모드 13h (320x200 256 색)를 사용했습니다. 모드 13h에서, 비디오 메모리는 픽셀마다 순차적으로 배치된다. 즉, 픽셀의 위치를 ​​계산하기 위해 다음 수학을 사용합니다.

memoryOffset = (row * 320) + column

요즘 시대에는 속도가 중요했기 때문에 비트 시프트를 사용하여이 작업을 수행했습니다.

그러나 320은 2의 거듭 제곱이 아니므로이 문제를 해결하려면 함께 더한 2의 거듭 제곱이 320을 만드는 것을 찾아야합니다.

(row * 320) = (row * 256) + (row * 64)

이제 왼쪽 시프트로 변환 할 수 있습니다.

(row * 320) = (row << 8) + (row << 6)

최종 결과 :

memoryOffset = ((row << 8) + (row << 6)) + column

고가의 곱셈 연산 대신 두 개의 비트 시프트를 사용한다는 점을 제외하고는 이전과 동일한 오프셋을 얻습니다. 몇 가지 실수와 32 비트 예제를 추가했습니다))

mov ax, 320; 2 cycles
mul word [row]; 22 CPU Cycles
mov di,ax; 2 cycles
add di, [column]; 2 cycles
; di = [row]*320 + [column]

; 16-bit addressing mode limitations:
; [di] is a valid addressing mode, but [ax] isn't, otherwise we could skip the last mov

전체 : 고대 CPU가 이러한 타이밍을 가졌을 때마다 28주기.

Vrs

mov ax, [row]; 2 cycles
mov di, ax; 2
shl ax, 6;  2
shl di, 8;  2
add di, ax; 2    (320 = 256+64)
add di, [column]; 2
; di = [row]*(256+64) + [column]

동일한 고대 CPU에서 12주기.

예, 우리는 16 번의 CPU 사이클을 줄이기 위해 열심히 노력할 것입니다.

32 또는 64 비트 모드에서 두 버전 모두 훨씬 짧아지고 빠릅니다. Intel Skylake ( http://agner.org/optimize/ 참조 ) 와 같은 최신 비 순차적 실행 CPU 는 매우 빠른 하드웨어 곱셈 (낮은 대기 시간 및 높은 처리량)을 가지므로 이득이 훨씬 작습니다. AMD 불도저 제품군은 특히 64 비트 곱하기에 약간 느립니다. Intel CPU 및 AMD Ryzen에서 두 가지 변화는 대기 시간이 약간 적지 만 곱하기보다 더 많은 명령어 수 (처리량 감소로 이어질 수 있음) :

imul edi, [row], 320    ; 3 cycle latency from [row] being ready
add  edi, [column]      ; 1 cycle latency (from [column] and edi being ready).
; edi = [row]*(256+64) + [column],  in 4 cycles from [row] being ready.

vs.

mov edi, [row]
shl edi, 6               ; row*64.   1 cycle latency
lea edi, [edi + edi*4]   ; row*(64 + 64*4).  1 cycle latency
add edi, [column]        ; 1 cycle latency from edi and [column] both being ready
; edi = [row]*(256+64) + [column],  in 3 cycles from [row] being ready.

컴파일러는이를 위해 다음을 수행합니다 . 최적화 할 때 GCC, Clang 및 Microsoft Visual C ++가 모두 shift + lea를 사용return 320*row + col; 하는 방법을 확인하십시오 .

여기서 가장 주목할만한 점은 x86에는LEA 작은 왼쪽 시프트를 수행하고 동시에 명령어로 수행 할 수 있는 시프트 앤 추가 명령어 ( ) 가 있다는 것 add입니다. ARM은 더욱 강력합니다. 명령의 피연산자 하나를 왼쪽이나 오른쪽으로 자유롭게 이동할 수 있습니다. 따라서 2의 거듭 제곱으로 알려진 컴파일 시간 상수에 의한 스케일링은 곱하는 것보다 훨씬 효율적일 수 있습니다.


좋아, 현대에 ... 이제 더 유용한 것은 비트 시프 팅을 사용하여 두 개의 8 비트 값을 16 비트 정수로 저장하는 것입니다. 예를 들어, C #에서 :

// Byte1: 11110000
// Byte2: 00001111

Int16 value = ((byte)(Byte1 >> 8) | Byte2));

// value = 000011111110000;

C ++에서 struct두 개의 8 비트 멤버와 함께 a를 사용한 경우 컴파일러 에서이를 수행해야하지만 실제로는 항상 그렇지는 않습니다.


8
이것을 확장하면 인텔 프로세서 (및 다른 많은 프로세서)에서이를 수행하는 것이 더 빠릅니다. int c, d; c = d << 2; 이것보다 : c = 4 * d; 때로는 "c = d << 2 + d << 1"조차 "c = 6 * d"보다 빠릅니다 !! DOS 시대의 그래픽 기능을 위해 이러한 트릭을 광범위하게 사용했는데 더 이상 유용하지 않다고 생각합니다.
Joe Pineda

5
@James : 요즘은 CPU가 아닌 GPU가 실행하는 비디오 카드의 펌웨어가 아닙니다. 따라서 이론적으로 그래픽 기능을 위해 이와 같은 코드를 구현할 필요가 없습니다 (또는 Carmack의 블랙 매직 역 루트 함수) :-)
Joe Pineda

3
@JoePineda @james 컴파일러 작성자는 확실히 사용하고 있습니다. 글을 쓰면 c=4*d변화가 생길 것입니다. 당신이 쓰는 경우 k = (n<0)에도 교대와 함께 할 수 있습니다 : k = (n>>31)&1분기를 피하십시오. 결론적으로, 컴파일러의 영리성 향상은 이제 C 코드에서 이러한 트릭을 사용할 필요가 없으며 가독성과 이식성을 손상시킵니다. 예를 들어 SSE 벡터 코드를 작성하는 경우이를 아는 것이 여전히 좋습니다. 또는 빠른 속도가 필요한 상황에서 컴파일러가 사용하지 않는 트릭이 있습니다 (예 : GPU 코드).
greggo

2
또 다른 좋은 예 : 두 가지 조건부 테스트를 하나로 변경하는 것이 큰 속도 이점 이 if(x >= 1 && x <= 9)될 수 있으므로 매우 일반적입니다 if( (unsigned)(x-1) <=(unsigned)(9-1)). 특히 분기 대신 술어 실행을 허용하는 경우. 10 년 전 abt가 컴파일러가 최적화 프로그램 에서이 변환을 시작했다는 것을 알 때까지 이것을 수년간 (정당화 된 곳) 사용했습니다. 컴파일러가 변환을 수행 할 수없는 유사한 상황이 있기 때문에 여전히 알아 두어야합니다. 또는 컴파일러로 작업하는 경우.
greggo

3
"바이트"가 단지 7 비트 인 이유가 있습니까?
메이슨 Watmough

104

비트 시프트를 포함한 비트 단위 연산은 저수준 하드웨어 또는 임베디드 프로그래밍의 기본입니다. 장치 또는 일부 이진 파일 형식에 대한 사양을 읽으면 바이트, 워드 및 dword가 다양한 관심 대상 값을 포함하는 바이트 단위로 정렬되지 않은 비트 필드로 분류 된 것을 볼 수 있습니다. 읽기 / 쓰기를 위해 이러한 비트 필드에 액세스하는 것이 가장 일반적인 사용법입니다.

그래픽 프로그래밍에서 간단한 실제 예는 16 비트 픽셀이 다음과 같이 표현된다는 것입니다.

  bit | 15| 14| 13| 12| 11| 10| 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1  | 0 |
      |       Blue        |         Green         |       Red          |

녹색 가치를 얻으려면 다음과 같이하십시오.

 #define GREEN_MASK  0x7E0
 #define GREEN_OFFSET  5

 // Read green
 uint16_t green = (pixel & GREEN_MASK) >> GREEN_OFFSET;

설명

오프셋 5에서 시작하여 10 (즉, 6 비트 길이)으로 끝나는 녹색 만 값을 얻으려면 전체 16 비트 픽셀에 적용 할 때 (비트) 마스크를 사용해야합니다. 우리가 관심있는 비트 만.

#define GREEN_MASK  0x7E0

적절한 마스크는 0x7E0이며 이진수는 0000011111100000 (십진수 2016)입니다.

uint16_t green = (pixel & GREEN_MASK) ...;

마스크를 적용하려면 AND 연산자 (&)를 사용하십시오.

uint16_t green = (pixel & GREEN_MASK) >> GREEN_OFFSET;

마스크를 적용한 후 MSB가 11 비트에 있기 때문에 실제로는 11 비트 숫자 인 16 비트 숫자로 끝납니다. 녹색은 실제로 6 비트 길이이므로 오른쪽 이동 (11-6 = 5)을 사용하여 축소해야하므로 5를 오프셋 ( #define GREEN_OFFSET 5)으로 사용합니다.

2의 거듭 제곱으로 빠른 곱셈 및 나눗셈을 위해 비트 시프트를 사용하는 것도 일반적입니다.

 i <<= x;  // i *= 2^x;
 i >>= y;  // i /= 2^y;

1
0x7e0은 10 진수로 2016 인 11111100000과 같습니다.
Saheed

50

비트 마스킹 및 쉬프팅

비트 시프 팅은 종종 저수준 그래픽 프로그래밍에 사용됩니다. 예를 들어, 주어진 픽셀 색상 값은 32 비트 워드로 인코딩됩니다.

 Pixel-Color Value in Hex:    B9B9B900
 Pixel-Color Value in Binary: 10111001  10111001  10111001  00000000

더 나은 이해를 위해 어떤 섹션으로 레이블이 지정된 동일한 이진 값은 어떤 색상 부분을 나타냅니다.

                                 Red     Green     Blue       Alpha
 Pixel-Color Value in Binary: 10111001  10111001  10111001  00000000

예를 들어이 픽셀 색상의 녹색 값을 얻고 싶다고 가정 해 봅시다. 우리는 마스킹시프트를 통해 그 가치를 쉽게 얻을 수 있습니다 .

우리의 마스크 :

                  Red      Green      Blue      Alpha
 color :        10111001  10111001  10111001  00000000
 green_mask  :  00000000  11111111  00000000  00000000

 masked_color = color & green_mask

 masked_color:  00000000  10111001  00000000  00000000

논리 &연산자는 마스크가 1 인 값만 유지되도록합니다. 이제 마지막으로해야 할 일은 모든 비트를 오른쪽으로 16 자리 (논리적 오른쪽 이동) 만큼 이동하여 올바른 정수 값을 얻는 것 입니다.

 green_value = masked_color >>> 16

즉, 픽셀의 색상에서 녹색의 양을 나타내는 정수가 있습니다.

 Pixels-Green Value in Hex:     000000B9
 Pixels-Green Value in Binary:  00000000 00000000 00000000 10111001
 Pixels-Green Value in Decimal: 185

이는 종종 같은 부호화 또는 이미지 포맷을 디코딩하기 위해 사용되는 jpg, png등등


32 비트 cl_uint와 같은 원본을 cl_uchar4와 같이 캐스팅하고 * .s2로 직접 원하는 바이트에 액세스하는 것이 쉽지 않습니까?
David H Parry

27

한 가지 문제는 다음이 구현에 따라 다릅니다 (ANSI 표준에 따름).

char x = -1;
x >> 1;

x는 이제 127 (01111111) 또는 여전히 -1 (11111111) 일 수 있습니다.

실제로는 대개 후자입니다.


4
올바르게 기억한다면 ANSI C 표준은 명시 적으로 구현에 따라 다르므로 코드에서 부호있는 정수를 오른쪽으로 이동하려면 컴파일러 설명서를 확인하여 구현 방법을 확인해야합니다.
Joe Pineda

예, 저는 ANSI 표준 자체를 강조하고 싶었습니다. 벤더가 단순히 표준을 따르지 않거나 표준이이 사건에 대해 아무 말도하지 않는 경우가 아닙니다.
Joe Pineda

22

팁과 요령 만 쓰고 있습니다. 시험 및 시험에 유용 할 수 있습니다.

  1. n = n*2: n = n<<1
  2. n = n/2: n = n>>1
  3. n이 2의 거듭 제곱인지 확인 (1,2,4,8, ...) : 확인 !(n & (n-1))
  4. x 번째 비트 얻기 n:n |= (1 << x)
  5. x가 짝수인지 홀수인지 확인 : x&1 == 0(짝수)
  6. x 의 n 번째 비트를 토글합니다 .x ^ (1<<n)

지금까지 몇 가지 더 알고 계십니까?
ryyker

@ryyker 몇 가지 더 추가했습니다. 나는 그것을 계속 업데이트하려고 노력할 것이다 :)
Ravi Prakash

x와 n 0이 색인되어 있습니까?
reggaeguitar

광고 5 : 음수이면 어떻게 되나요?
피터 Mortensen

이진수의 2가 10의 10과 같다는 결론을 내릴 수 있습니까? 비트 이동은 다른 숫자 뒤에 하나 이상의 숫자를 더하거나 빼는 것과 같습니다.
Willy satrio nugroho

8

Java 구현에서 시프트 할 비트 수는 소스 크기에 따라 조정됩니다.

예를 들면 다음과 같습니다.

(long) 4 >> 65

비트를 오른쪽으로 65 번 이동하면 모든 것이 0이 될 것으로 예상 할 수 있지만 실제로는 다음과 같습니다.

(long) 4 >> (65 % 64)

이것은 <<, >> 및 >>>에 해당됩니다. 나는 다른 언어로 시도하지 않았습니다.


허, 흥미 롭습니다! C에서 이것은 기술적으로 정의되지 않은 동작 입니다. gcc 5.4.0경고를 제공하지만 25 >> 65를 제공 합니다. 게다가.
pizzapants184

2

파이썬에서 유용한 비트 연산 / 조작.

나는 구현 라비 프라 카쉬의 답변을 파이썬.

# Basic bit operations
# Integer to binary
print(bin(10))

# Binary to integer
print(int('1010', 2))

# Multiplying x with 2 .... x**2 == x << 1
print(200 << 1)

# Dividing x with 2 .... x/2 == x >> 1
print(200 >> 1)

# Modulo x with 2 .... x % 2 == x & 1
if 20 & 1 == 0:
    print("20 is a even number")

# Check if n is power of 2: check !(n & (n-1))
print(not(33 & (33-1)))

# Getting xth bit of n: (n >> x) & 1
print((10 >> 2) & 1) # Bin of 10 == 1010 and second bit is 0

# Toggle nth bit of x : x^(1 << n)
# take bin(10) == 1010 and toggling second bit in bin(10) we get 1110 === bin(14)
print(10^(1 << 2))

-3

Windows 플랫폼에서는 32 비트 버전의 PHP 만 사용할 수 있습니다.

그런 다음 예를 들어 << 또는 >>를 31 비트 이상 시프트하면 결과를 예상 할 수 없습니다. 일반적으로 0 대신 원래 숫자가 반환되며 실제로 까다로운 버그 일 수 있습니다.

물론 64 비트 버전의 PHP (Unix)를 사용하는 경우 63 비트 이상 이동하지 않아야합니다. 그러나 예를 들어 MySQL은 64 비트 BIGINT를 사용하므로 호환성 문제가 없어야합니다.

업데이트 : PHP 7 Windows에서 PHP 빌드는 마침내 전체 64 비트 정수를 사용할 수 있습니다. 정수 의 크기는 플랫폼에 따라 다르지만 최대 약 20 억 값이 일반적인 값 (32 비트 부호)입니다. 64 비트 플랫폼은 보통 최대 32 비트 인 PHP 7 이전의 Windows를 제외하고 최대 약 9E18입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.