구조 부재를 오프셋으로 가져오거나 설정하려면 어떻게 해야 합니까?
패딩/정렬 문제를 무시하고 다음과 같은 구조를 고려할 때, 멤버 이름을 사용하지 않고 member_b 값을 얻고 설정하는 가장 좋은 방법은 무엇입니까?
struct mystruct {
int member_a;
int member_b;
}
struct mystruct *s = malloc(sizeof(struct mystruct));
다른 말로 하자면, 다음을 포인터/오프셋으로 어떻게 표현하시겠습니까?
s->member_b = 3;
printf("%i",s->member_b);
내 추측으로는
- member_a의 크기를 구하여 오프셋을 계산합니다(
int
) - 구조를 단일 단어 포인터 유형으로 캐스트(
char
?) - 창조하다, 창안
int
포인터를 가리키고 주소를 설정합니다.*charpointer + offset
?) - 내꺼 써요
int
메모리 내용을 설정할 포인터
하지만 나는 캐릭터 타입에 캐스팅하는 것에 대해 약간 혼란스러워하거나 아니면 비슷한 것을.memset
더 적절하거나 일반적으로 제가 이것을 완전히 틀리게 접근하고 있습니다.
도움이 되시길 응원합니다.
당신이 개략적으로 설명한 접근 방식은 대략 정확하지만, 당신은 다음을 사용해야 합니다.offsetof
스스로 상쇄를 파악하는 대신에 말입니다.왜 당신이 그 일을 언급하는지 잘 모르겠습니다.memset
-- 블록의 내용을 지정된 값으로 설정합니다. 이 값은 당면한 질문과 전혀 관련이 없어 보입니다.
작동 방식을 설명하기 위한 코드는 다음과 같습니다.
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
typedef struct x {
int member_a;
int member_b;
} x;
int main() {
x *s = malloc(sizeof(x));
char *base;
size_t offset;
int *b;
// initialize both members to known values
s->member_a = 1;
s->member_b = 2;
// get base address
base = (char *)s;
// and the offset to member_b
offset = offsetof(x, member_b);
// Compute address of member_b
b = (int *)(base+offset);
// write to member_b via our pointer
*b = 10;
// print out via name, to show it was changed to new value.
printf("%d\n", s->member_b);
return 0;
}
전체 기법:
다음의 오프셋을 사용하여 오프셋을 가져옵니다.
b_offset =의 오프셋(struct my structor, member_b);
구조의 주소를 문자 * 포인터로 가져옵니다.
char *sc = (char *)s;
구조물 주소에 간격띄우기 추가를 추가하고, 값을 포인터에 적절한 유형으로 캐스팅한 후 참조를 해제합니다.
*(int *)(sc + b_offset)
패딩과 얼라인먼트를 무시한 채로 말입니다.
예에서와 같이 지시하는 요소가 전체적으로 단일 유형일 경우 구조를 원하는 유형으로 캐스트한 후 배열로 처리할 수 있습니다.
printf("%i", ((int *)(&s))[1]);
구조와 NULL을 기준 포인터로 하여 오프셋을 계산할 수 있습니다. 예를 들어 "&((타입 *)0)->필드"
예:
struct my_struct {
int x;
int y;
int *m;
int *h;
};
int main()
{
printf("offset %d\n", (int) &((((struct my_struct*)0)->h)));
return 0;
}
이 예에서는 다음을 통해 해결할 수 있습니다.*((int *) ((char *) s + sizeof(int)))
. 왜 그러시는지 잘 모르니 교훈적인 취지를 전제로 하고 있으니 설명을 따르겠습니다.
코드의 비트는 다음과 같이 번역됩니다: 주소에서 시작하는 메모리를 가져와 다음을 가리키는 메모리로 취급합니다.char
. 해당 주소에 추가합니다.sizeof(int)
char
- chunks - 새 주소가 표시됩니다.주소가 생성한 값을 사용하여 다음과 같이 취급합니다.int
.
주의할 점은 다음과 같습니다.*(s + sizeof(int))
주소는 다음과 같습니다.s
플러스로sizeof(int)
(mystruct) 청크 크기
편집: Andrey의 코멘트에 따르면, 오프셋을 사용하여:
*((int *) ((byte *) s + offsetof(struct mystruct, member_b)))
편집 2: 모두 교체했습니다.byte
에 를 char
잿더미로sizeof(char)
1로 보장됩니다.
여러분이 실제로 하고 있는 일은 다양한 데이터 유형을 하나의 메모리 블록으로 포장하고 압축을 푸는 것입니다.직접 포인터 캐스트를 사용하면 이 작업에서 벗어날 수 있지만, 다른 대부분의 답변에서는 다음과 같이 제시하고 있습니다.
void set_int(void *block, size_t offset, int val)
{
char *p = block;
*(int *)(p + offset) = val;
}
int get_int(void *block, size_t offset)
{
char *p = block;
return *(int *)(p + offset);
}
문제는 이것이 휴대가 불가능하다는 것입니다.블록 내에 올바른 정렬 상태로 유형을 저장할 수 있는 일반적인 방법은 없으며, 일부 아키텍처에서는 정렬되지 않은 주소에 로드나 저장을 수행할 수 없습니다.블록의 레이아웃이 선언된 구조물로 정의되는 특수한 경우에는 구조물 레이아웃에 올바른 정렬을 보장하는 데 필요한 패딩이 포함되므로 괜찮습니다.하지만 이름으로 접속할 수 없기 때문에 이것은 실제로 당신이 하는 일이 아닌 것처럼 들립니다.
휴대용으로 이 작업을 수행하려면 다음을 사용해야 합니다.memcpy
:
void set_int(void *block, size_t offset, int val)
{
char *p = block;
memcpy(p + offset, &val, sizeof val);
}
int get_int(void *block, size_t offset)
{
char *p = block;
int val;
memcpy(&val, p + offset, sizeof val);
return val;
}
(다른 유형과 유사함).
언급URL : https://stackoverflow.com/questions/2043871/how-can-i-get-set-a-struct-member-by-offset
'source' 카테고리의 다른 글
앱이 다시 시작되지 않고 다시 시작됨 (0) | 2023.10.29 |
---|---|
컨테이너의 나머지 너비를 채우는 스타일 입력 요소 (0) | 2023.10.29 |
Python - 새 줄로 연결 (0) | 2023.10.29 |
@Service 클래스의 스프링 부트 캐싱이 작동하지 않음 (0) | 2023.10.29 |
중첩 함수 구현 (0) | 2023.10.29 |