2010-04-05 5 views
3

포인터 연산의 경우 정수가 자동으로 부호있는 변형으로 변환됩니까? 그렇다면 왜?포인터 산술 & 부호있는/부호없는 변환!

은 가정하자 나는, 나는 왜의 부호 값이 포인터의 주소가 4 씩 감소 얻을

int *pointer; 
int *pointerdiff; 
unsigned int uiVal = -1; 

pointerdiff = pointer + uiVal // Pointer will contain valid address here. 
포인터가 int로하고 uiVal -1로 초기화되는 포인터입니다

를 찾을 수 있습니까 -1 여기서는 고려하지 않습니까?

+2

그래서 uiVal은 부호없는 int입니까? 아마 당신은 나를 추측하기보다는 좀 더 많은 코드를 게시 할 수 있습니다. 서명되지 않은 경우 uiVal은 -1이 될 수 있습니까? – WhirlWind

+0

죄송합니다. 내 게시물을 수정했습니다. 희망은 지금 괜찮습니다. 추가로 편집 할 수 있다고 생각되면 자유롭게 편집하십시오. 감사! – Jay

답변

8

포인터가 넘칠 것 같습니다.

몇 가지 수학을 해보 죠. 32 비트 컴퓨터에서 포인터가 0x 12 34 56 78으로 초기화되었다고 가정 해보십시오. 그런 다음 부호없는 int 변수를으로 초기화합니다.이 변수는 -1입니다. 0x FF FF FF FF입니다. 부호없는 정수이기 때문에 -1은 넘쳐 흐르고 실제로는 4 294 967 295을 나타냅니다.

포인터가 정수 (int*)로되어 있으므로 각 증분은 실제로 주소를 sizeof int (표준 x86 컴퓨터에서는 4)으로 증가시킵니다. 따라서 실제로는 0x 03 FF FF FF FC (즉 0x FF FF FF FF * 4)을 추가하고 있습니다.

이제 두 항목을 함께 추가해 보겠습니다. 우리는 지금 40 비트 값을 가지고 있기 때문에 물론

0x 00 12 34 56 78 
+ 0x 03 FF FF FF FC 
------------------- 
    0x 04 12 34 56 74 

,이, 오버 플로우 및 포인터는 32 비트 및 해당 많은 정보를 보유 할 수 있습니다. 따라서 우리는 처음에 04을 잃게됩니다.결과는 0x 12 34 56 74이고 0x 12 34 56 78 - 4입니다.

3

예, 정수 피연산자가 승격됩니다. 그러나 여기에는 그다지 중요하지 않습니다. uiVal은 부호가없는 유형 인 경우 -1이 될 수 없습니다. 아마 당신은

unsigned int uiVal = -1; 
pointer + uiVal ... 

을했다하지만 그

pointer + UINT_MAX ... 

과 동일 할 것입니다 그리고 포인터를 저장할 수있는 주소 범위이 또한 극복 할 수없는 경우이 정의되지 않은 동작이 발생할 가능성이 높습니다. 표준이 연산자의 목적 5.7/4

에서, nonarray 오브젝트 포인터가 요소 형식으로 객체의 타입 길이 하나의 어레이의 첫 번째 요소의 포인터와 같은 동작 말한다 .

정수 유형을 갖는 표현식이 포인터에 추가되거나 포인터에서 제거 될 때 결과에는 포인터 피연산자 유형이 있습니다. 포인터 피연산자가 배열 객체의 요소를 가리키고 배열의 크기가 충분히 크면 [...]. 포인터 피연산자와 결과가 동일한 배열 객체의 요소를 가리 키거나 결과가 배열 객체의 마지막 요소를 지나는 경우 평가에서 오버플로가 발생하지 않아야합니다. 이면, 동작은 정의되지 않습니다. 결과 포인터가 같은 배열에 거짓말을하거나 말 지난 1, 아니면 않지만 오버 플로우에 의해 그렇게하면, 동작이 정의되지 않는 경우입니다

.

+0

하지만, 요점은, 그것은 나에게 정의되지 않은 행동을 제공하지 않는다는 것입니다. 오히려 -1과 같은 행동을합니다. 이것은 나를 놀라게하는 것입니다. – Jay

+1

@ Jay, 행동이 정의되지 않는다는 것은 당신이 항상 똑같은 행동을한다는 ​​것을 포함해서 어떤 일이 일어날 수 있음을 의미합니다. 반드시 segfault를 얻는다는 의미는 아닙니다. 32 비트 부호없는 int를 가진 64 비트 플랫폼에서, 당신은 다른 행동을 취하게 될 것입니다. –

0

오른쪽 피연산자가 서명 된 것으로 보이는 ptrdiff_t 유형으로 형 변환된다고 생각합니다.