질문 배경: C 언어는 저수준 메모리 및 다양한 플랫폼 작업을 용이하게 하기 위해 유형 변환에 대해 유연성을 제공했습니다. 그러나 그 간결함과 강력함은 잘못된 유형 변환으로 인한 취약성과 결함으로 이어질 수 있습니다. 특히 포인터와 비트 연산을 사용할 때 주의해야 합니다.
문제:
해결책:
코드 예제:
#include <stdio.h> void print_double_as_int(double d) { int i = (int)d; printf("Value: %d\n", i); } void *ptr = malloc(16); int *ip = (int*)ptr; // 기본 메모리에 접근: ptr가 실제로 int를 가리킬 경우 허용
주요 특징:
1. void*를 구조체 포인터로 변환할 수 있는 경우와 항상 안전한지?
이러한 변환은 주소가 실제로 해당 구조체의 인스턴스를 가리킬 경우 안전하지만, 그렇지 않으면 동작이 정의되지 않습니다.
2. 동일한 길이의 구조체 포인터를 필드 수가 더 적거나 많은 구조체 포인터로 변환하면 무엇이 발생합니까?
'새로운' 구조체의 필드에 접근하면 원래 구조체의 경계를 넘어 읽기/쓰기하게 되어 데이터가 손상될 수 있습니다.
코드 예제:
typedef struct {int a;} S1; typedef struct {int a; int b;} S2; S1 s; S2 *ps2 = (S2*)&s; // ps2->b는 "쓰레기"에서 접근
3. int 포인터를 char 포인터로 안전하게 변환하여 이 숫자의 바이트에 접근할 수 있습니까?
이는 메모리 작업의 전형적인 방법 중 하나입니다. 바이트 단위 접근은 허용되지만, 정렬 문제와 바이트 순서가 아키텍처에 따라 다를 수 있으므로 주의가 필요합니다 (big-endian/little-endian).
주니어 프로그래머가 접근 시간을 최적화하기 위해 네트워크 패킷을 처리하면서 raw 배열의 포인터를 서로 다른 유형의 필드를 가진 데이터 구조의 포인터로 변환했습니다.
장점:
단점:
수정 후 각 패킷의 바이트는 memcpy를 통해 수동으로 추출되었습니다.
장점:
단점: