기능 포인터를 포맷하는 방법?
ANSI C에서 함수에 대한 포인터를 인쇄할 수 있는 방법이 있는가?물론 이것은 당신이 기능 포인터를 보이드 포인터에 던져야 한다는 것을 의미하지만, 그것은 불가능해 보입니까?
#include <stdio.h>
int main() {
int (*funcptr)() = main;
printf("%p\n", (void* )funcptr);
printf("%p\n", (void* )main);
return 0;
}
$gcc -ansi -pedantic -Wall test.c -o test
test.c: 함수 'main'에서:
test.c:6: warning: ISO C에서는 기능 포인터를 개체 포인터 유형으로 변환하는 것을 금지함
test.c:7: warning: ISO C에서는 기능 포인터를 개체 포인터 유형으로 변환하는 것을 금지함
$ ./테스트
0x400518
0x400518
'작동'이지만 비표준적인...
이를 위한 유일한 합법적인 방법은 문자 유형을 사용하여 포인터를 구성하는 바이트에 접근하는 것이다.다음과 같은 경우:
#include <stdio.h>
int main() {
int (*funcptr)() = main;
unsigned char *p = (unsigned char *)&funcptr;
size_t i;
for (i = 0; i < sizeof funcptr; i++)
{
printf("%02x ", p[i]);
}
putchar('\n');
return 0;
}
l값 유형으로 함수 포인터 바이트 검사void *
, 또는 모든 비문자 유형은 정의되지 않은 행동이다.
함수 포인터를 구성하는 바이트들이 실제로 의미하는 것은 구현에 의존한다는 것이다.예를 들어, 함수 테이블로 인덱스를 나타낼 수도 있고, 함수 포인터를 통해 호출할 때 기호 테이블에서 검색되는 함수 이름의 첫 번째 N 문자가 될 수도 있다.함수 포인터에서 지원되어야 하는 유일한 연산은 그것을 통해 함수를 호출하고 엄격한 동일성/부질성을 위해 다른 함수 포인터 또는 NULL과 비교하는 것이므로, 구현 방식에 있어서 매우 넓은 위도를 이용할 수 있다.
gcc 4.3.4의 경우 스위치 -O2 -Wstrct-alliasing을 사용하면 드림락스의 대답은 다음과 같다.
warning: dereferencing type-punned pointer will break strict-aliasing rules
추가: 나는 내성과 크기에 대한 카페의 답변에 대한 반대는 타당하다고 생각하는데, 이것은 그의 해결책이 다루지 않는다(말장난 의도된 것은 아니다).더스틴의 노조 출연진 사용에 대한 제안은 아마도 합법적일 것이다. (내가 읽은 바에 의하면 거기에 약간의 논쟁이 있는 것 같지만, 당신의 컴파일러가 하는 것은 법보다 중요하다.)그러나 그의 코드는 단 한 명의 라이너에 의해 단순화(또는 당신의 취향에 따라 난독화)될 수 있다.
printf("%p\n", ((union {int (*from)(void); void *to;})funcptr).to);
이를 통해 gcc의 엄격한 별칭 경고가 제거된다(그러나 '정확한' 것인가).
-pedantic 스위치를 사용하거나 SGI IRIX를 사용하는 경우 Aggregate cast가 '작동'되지 않으므로 다음을 사용하십시오.
printf("%p\n", ((union {int (*from)(void); void *to;} *)&funcptr)->to);
그러나 원래의 질문에 대해서는: 그것의 기원은 -pedantic의 사용에 있다. 나는 이것이 약간 현학적인 것이라고 생각한다.
추가 편집:다음 예에서와 같이 마지막 예에서는 주체를 사용할 수 없다는 점에 유의하십시오.
printf("%p\n", ((union {int (*from)(void); void *to;}) main).to); // ok
printf("%p\n", ((union {int (*from)(void); void *to;} *)&main)->to); // wrong!
물론 메인 디케이스를 메인 디케이팅을 하기 때문이다.
다음을 시도해 보십시오.
#include <stdio.h>
#include <inttypes.h>
int main() {
int (*funcptr)() = main;
unsigned char *p = (unsigned char *)&funcptr;
int i;
/* sample output: 00000000004005e0 */
printf("%016"PRIxPTR"\n", (uintptr_t)main);
/* sample output: 00000000004005e0 */
printf("%016"PRIxPTR"\n", (uintptr_t)funcptr);
/* reflects the fact that this program is running on little-endian machine
sample output: e0 05 40 00 00 00 00 00 */
for (i = 0; i < sizeof funcptr; i++)
{
printf("%02x ", p[i]);
}
putchar('\n');
return 0;
}
다음 플래그 사용:
gcc -ansi -pedantic -Wall -O2 -Wstrict-aliasing c.c
해당 플래그를 사용하여 경고가 발생하지 않음
함수 포인터를 정수에 캐스팅한 다음 다시 포인터에 캐스팅하여 "%p"를 사용하십시오.
#include <stdio.h>
int main() {
int (*funcptr)() = main;
printf("%p\n", (void *)(size_t) funcptr);
printf("%p\n", (void *)(size_t) main);
return 0;
}
일부 플랫폼(예: "중간" 또는 "콤팩트" 메모리 모델의 16비트 DOS)에서는 데이터에 대한 포인터와 함수에 대한 포인터의 크기가 동일하지 않다는 점에 유의하십시오.
경고/오류를 극복할 수 있는 조합의 사용이 있지만, 결과는 여전히 (대부분의) 정의되지 않은 행동이다.
#include <stdio.h>
int
main (void)
{
union
{
int (*funcptr) (void);
void *objptr;
} u;
u.funcptr = main;
printf ("%p\n", u.objptr);
return 0;
}
두 가지 기능 포인터를 비교할 수 있다(예:printf ("%i\n", (main == funcptr));
) if 문구를 사용하여 동일 여부를 테스트한다(나는 목적을 완전히 무너뜨리고 매우 무관할 수 있다는 것을 알고 있다). 그러나 실제로 함수 포인터 주소를 출력하는 한, 어떤 일이 발생하는지는 목표 플랫폼의 C 라이브러리와 컴파일러의 벤더에게 달려 있다.
이것이 정직한지는 잘 모르겠지만 루프, 유니온, 비점퍼 타입에 대한 깁스, 또는 그 외 추가적인 의존성 없이 효과를 얻는다.string.h
int (*funcptr)() = main;
void* p = NULL;
memcpy(&p, (void**) &funcptr, sizeof(funcptr));
printf("%p", p);
withgo 과 함께 gcc -ansi -pedantic -Wall -Wstrict-aliasing
GCC 7.1.1에 의거하여
참조URL: https://stackoverflow.com/questions/2741683/how-to-format-a-function-pointer
'Programing' 카테고리의 다른 글
SSR을 지원하는 Vue-cli 3 구성 요소 라이브러리 (0) | 2022.04.18 |
---|---|
vuex의 API에서 데이터를 올바르게 가져오는 방법 (0) | 2022.04.18 |
이 Valgrind 경고의 의미는? - 경고 설정 주소 범위(Perms (0) | 2022.04.17 |
크기를 조정하려면 탐색 드로어 끌기 (0) | 2022.04.17 |
로그아웃 시 vuex 비어 있는 상태 (0) | 2022.04.17 |