2009-07-11 3 views
1

다음 코드 :또 다른 C 포인터 질문

int *a; 
*a = 5; 

가능성이 가장 높은 세그먼트 오류의 결과와 나는 이유를 알 수 있습니다.

다음 코드 :

int a; 
*a = 5; 

도 컴파일되지 않습니다. (gcc 메시지 : unary *의 잘못된 유형 인수).

이제 포인터는 주소를 저장하기 위해 으로 사용되는 정수입니다.

*a = 5; 

이상적으로,이 또한 세그먼트 오류 발생한다 : 그래서, 왜 내가 말한다면 문제가 될 것이다.

+4

포인터는 부호없는 서수 스칼라이며 반드시 정수는 아닙니다. – fortran

+1

일관성/명료성을 위해 세그먼트 오류를 ​​예상하는 것이 이와 같은 상황에서 행동을 생각하는 데 지나치게 정확한 방법은 아니라는 점에 유의해야합니다. 임의의 메모리 주소를 참조 해제하는 것은 C에서 정의되지 않은 동작입니다. 대부분의 경우 세그멘테이션 오류가 발생하지만 필수는 아닙니다. 버스 오류가 발생할 수 있습니다 (Mac OS X은이를 원합니다). 주소가 유효 할 경우 해당 주소의 내용을 제공 할 수 있습니다. –

+0

'C '는 올바르게 초기화되지 않은 포인터를 감지하는 데 어려움이 있지만'int '데이터 유형을 참조 해제하지 않습니다. 그것을 컴파일하는 동안 당신을 멈추게합니다. 그러나 당신은'* (unsigned int *) a = 5'로 그것을 강제 할 수 있고 아마 당신이 기대하는 세분화 오류를 얻을 수 있습니다. 낮은 확률로 'a'는 프로그램 컨텍스트 내에서 주소 지정이 가능한 위치로 변환되는 값을 갖기 때문에 '어쩌면'이라고 말하면서 실수를 놓치지 만 무작위로 주소를 지정하는 미묘한 잘못을 달성하게됩니다. – nik

답변

1

첫 번째 경우에는 실제로 "a"를 할당하지 않습니다.

int* a = ? 
*a = 5; //BAD. What is 'a' exactly? 

int a = ? //but some int anyway 
*a = 5; //'a' is not a pointer! 

정수를 포인터로 사용하려면 먼저 캐스팅해야합니다. 포인터는 인 정수일 수 있지만 개념적으로는 다른 용도로 사용됩니다.

14

포인터는 이 아니고 정수입니다. C는 데이터

에 A 형) 특정 프로그래밍 오류를 방지하고,

b)는 그들이 진짜로 두 개의 정수로 구성되어 있기 때문에, 어떤 시스템

이 포인터는 정수에게하지 않을 수 있습니다 프로그램의 이식성을 향상 (세그먼트가 있습니다 오프셋). 다른 시스템에서는 int가 32 비트이고 포인터가 64 비트이므로 포인터를 나타내는 데 "int"유형을 사용할 수 없습니다. 이러한 이유로 C는 int를 포인터로 직접 사용하지 못하도록합니다. 포인터를 보유 할만큼 충분히 큰 정수 유형을 사용하려면 intptr_t를 사용하십시오.

-4

int * -는 int에 대한 포인터입니다. 아무데도 가리 키지 않았고 초기화하지 않았습니다. 그러한 질문을하기 전에 C에 관한 책을 읽으십시오.

+0

나는 그것이 왜 실패했는지 알기 위해 명시 적으로 썼습니다 ... 제 질문은 왜 두 번째 스 니펫이 컴파일되지 않았을까요? – dharm0us

+0

약간의 수업을 통해 답안에 여러 음절을 피할 수 있습니다. –

3

당신이 포인터하지 뭔가 역 참조 컴파일러를 만들기 위해 노력하고있다

int a; 
*a = 5; 

당신이 말할 때. 물론, 당신은 포인터로에게 캐스팅 수있는 다음 역 참조 그것을,

*((int*)a) = 5; 

.. 그리고 당신이 정말로, 정말로 그렇게 할 컴파일러를 알려줍니다, 그래서있다. 그러나 위험한 일입니다. 왜? 예를 들어, 예를 들어, 실제로는 a의 값을 초기화하지 않았으므로 포인터로 사용할 때 이미 a에 사용 된 위치에있는 값을 갖게됩니다. 로컬 변수 인 것처럼 보이므로 함수의 스택 프레임에서 초기화되지 않은 위치가되며 일 수 있습니다.입니다. 본질적으로, 당신은 어떤 미정의 위치에 값 5를 쓰려고 할 것입니다; 정말 현명한 일이 아닙니다!

2

포인터는 단순히 주소를 저장하고 주소는 정수와 마찬가지로 숫자로 생각할 수 있습니다.하지만 일반적으로 주소는 페이지 번호, 페이지 내 오프셋 등과 같은 구조를 가지고 있습니다.

당신은 한 마디로해서는 안됩니다. 정수는 문자 그대로 숫자를 저장합니다. 숫자를 더하거나 뺄 수는 있지만 포인터로 사용할 수는 없습니다. 정수는 정수이고, 포인터는 포인터입니다. 그들은 다른 목적을 가지고 있습니다.

때로는 포인터를 정수로 형변환해야 할 수도 있습니다 (어쨌든 OS 커널에서 일부 주소 계산을 수행하는 경우). 그런 다음 이전에 컴파일러가 올바른 크기를 보장하고 값을 유지하는지 여부를 파악한 후 정수 유형으로 포인터를 캐스팅 할 수 있습니다. 그러나 역 참조를 원할 경우 포인터 유형으로 다시 캐스트해야합니다.

0

연산자 *은 정수 데이터 형식에 대해 정의되지 않은 단항 연산자입니다. 문

*a = 5;

가 컴파일되지 않습니다 이유입니다.

또한 정수와 포인터는 서로 다릅니다. 일반적으로 메모리 크기는 동일합니다 (32 비트 시스템의 경우 4 바이트).