문제

실제 포인터를 값으로 보내지 않고 값은 포인터로 캐스팅됩니다. GTK 프로그램의 GUI 인터페이스 코드에서 이러한 예를 찾았습니다.

g_signal_connect (pastebutton[pane],
                  "clicked",
                  G_CALLBACK(on_paste_button_pressed),
                  (void*)((long)pane<<4));

위의 예에서는 마지막 매개 변수를 언급하고 있습니다. g_signal_connect. 언제 on_paste_button_pressed GTK2에 의해 호출됩니다. on_paste_button_pressed 캐스트 user_data Void Pointer가 그렇게 좋아요 :

int pane = ((long)user_data) >> 4;

실제로, 나는이 특정 예를 코드에 추가했지만 이미 존재하는 것을 기반으로합니다. 캐스팅에 대한 경고를 피하기 위해 비트 변화를 추가했습니다. 이 프로그램 자체에는 상당히 많은 위젯이 포함 된 4 개의 판이 있습니다. 복사 및 붙여 넣기 버튼을 사용하면 모든 값을 한 창에서 다른 창으로 복사 할 수 있습니다.

이러한 방법으로 값을 포인터 주소에 자주 사용하는 방법을 자주 사용하는 방법이며, 이것이 사용되지 않아야하는 이유가 있습니까?

편집하다:

정수에서 공허 포인터로의 캐스트는 다음과 같이 달성 할 수 있습니다.

void* void_ptr = some_int - NULL;
도움이 되었습니까?

해결책

그것은이다 사용된. 그것은이다 사용된 필요한 일을 할 때 일반적으로.

그것을 사용하지 않는 한 가지 이유는 이론적으로 포인터 크기가 소스 정수 크기보다 작을 수 있기 때문입니다.

사용하지 않는 또 다른 이유는 하나의 정수 데이터 만 콜백에 전달할 수 있기 때문입니다. 미래에 다른 데이터를 추가 해야하는 경우 (또는 비 인구로 전환 해야하는 경우) 콜백이 전달 된 데이터에 액세스하는 모든 장소를 찾아서 다시 작성해야합니다. 따라서 미래에 데이터를 확장해야 할 가능성이 있다면 struct (단 하나만 보유하더라도 int 이때) 그리고 그것에 대한 포인터를 전달하십시오 struct.

그러나 만약 당신이 당신이 당신이 그 단일 정수 이외의 다른 것을 전달할 필요가 없다고 확신한다면, 당신의 정수가 void *,이 기술은 어떤 식 으로든 깨지지 않습니다.

추신 Pedantically 말하면, C 나 C ++는 정수-투명 *-to-Integer 변환에 대한 왕복 보장을 갖지 않는 것으로 보이며, 즉 원래의 적분 값을 작동시키고 복원 할 것이라고 보장하지 않습니다.

다른 팁

macros gint_to_pointer () 및 gpointer_to_int ()를 사용하여 포인터와 정수 사이에 캐스트해야합니다.

glib : 변환 매크로를 입력하십시오

포인터에 정수를 캐스팅하는 것은 값을별로 전달하는 데 사용됩니다. 컴파일러가 포인터를 해석 할 필요가 없기 때문에 이는 회의 별 매개 변수가 필요한 경우 선호하는 방법입니다.

비트 변화는 오버플로를 유발할 수 있기 때문에 나쁜 생각입니다.

실제로 휴대용 코드의 경우 Intptr_t를 정수 유형으로 사용하여 포인터에 잘 맞습니다.

이런 종류의 경우에 사용됩니다. 그것은 많은 플랫폼에서 작동하지만 임의의 정수가 항상 유효한 포인터 값은 아니기 때문에 실패 할 수 있습니다. 포인터는 정수가 할 수있는 모든 값을 보유 할 수 없을 수도 있습니다. 64 비트를 사용하는 경우입니다. long 포인터가 32 비트 인 플랫폼에서는 물론 값을 바꾸기 때문에 포인터와 정수가 같은 크기 인 경우에도 실패 할 수도 있습니다. 이 트릭을 사용하려면 아마 확인해야합니다. sizeof (void*) 사용하는 정수 유형의 크기에 비해, 포인터가 충분하지 않은 경우 실제 값에 대해 런타임을 확인하십시오. 필요한 경우 플랫폼에서 실제 포인터를 사용하도록 완전 휴대용을 만들어내는 것은 가치가 없으므로이 트릭이 작동하는 플랫폼으로 제한하거나 트릭을 완전히 포기하십시오.

괜찮습니다. 사용 빈도에 대한 통계가 없지만 정말로 신경 쓰나요?

그래도 비트 시프트가 얼마나 도움이되는지 이해하지 못합니다.

그것은 사용되지만 결코 휴대용이 아니므로 조심해야합니다.

C 표준은 포인터 유형이 정수 유형만큼 적어도 많은 비트를 가지고 있어야하므로 항상 그렇게 할 수는 없습니다.

그러나 나는 기억할 수 없다 어느 포인터가 가진 플랫폼 실제로 정수보다 작았 기 때문에 아마도 안전하지는 않더라도 안전 할 것입니다 (기술적으로 안전하지는 않지만).

제가 주조가있을 수 있다고 생각할 수있는 유일한 이유는 정렬 경고의 가능성을 제거하는 것입니다. C1X 초안의 6.3.2.3 절에 :

정수는 모든 포인터 유형으로 변환 될 수 있습니다. 이전에 지정된 경우를 제외하고, 결과는 구현 정의되고, 올바르게 정렬되지 않을 수 있으며, 참조 된 유형의 엔티티를 가리키지 않을 수 있으며, 트랩 표현 일 수 있습니다.

이것은 C-FAQ에서 나온 것입니다.

큐: 정수는 포인터로 어떻게 오지 전환됩니까? 일시적으로 정수를 포인터에 넣을 수 있습니까?

A : 옛날 옛적에, 포인터가 정수로 변환 될 수 있음을 보장 받았다 (INT 또는 오래 필요한지 알지 못했지만 정수가 포인터로 변환 될 수 있고 포인터로 변환 될 수 있음을 보장했다. (충분히 큰) 정수로 변환 될 때 변경되지 않은 채로 남아 있었고, 다시 돌아 왔고, 전환 (및 모든 매핑)은``기계의 주소 지정 구조를 아는 사람들에게는 놀랍지 않은 ''라고 의도되었습니다. 정수/포인터 변환에 대한 일부 선례와 지원이지만 항상 기계 의존적이어서 포송 할 수 없었습니다. 명시 적 캐스트는 항상 필요했습니다 (초기 컴파일러는 당신이 그들을 맡겼을 때 거의 불만을 제기하지는 않았지만).

ANSI/ISO C 표준은 C가 널리 구현 가능하도록하기 위해 초기 보증을 약화시켰다. 포인터 투 인트거 및 정수-포인터 전환은 구현 정의되어 있으며 (질문 11.33 참조), 더 이상 포인터를 변경없이 정수와 뒤로 변환 할 수 있다는 보장이 없습니다.

포인터를 정수 또는 포인터로 정수로 강요하는 것은 결코 좋은 연습이 아닙니다. 어느 종류의 데이터를 보유 할 수있는 일반적인 슬롯이 필요할 때, 노조는 훨씬 더 나은 아이디어입니다.

질문 4.15, 5.18 및 19.25 질문도 참조하십시오.

참고 문헌 : K & R1 Sec. A14.4 p. 210 K & R2 SEC. A6.6 p. 199 ISO SEC. 6.3.4 이론적 근거 Sec. 3.3.4 H & S 초. 6.2.3 p. 170, Sec. 6.2.7 pp. 171-2

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top