c에서 구조 요소의 간격띄우기 찾기
struct a
{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
의 오프셋을 찾는 방법을 설명해 줄 수 있는 사람이 있습니까?int k
우리가 주소를 찾을 수 있도록.int i
?
사용하다offsetof()
시작부터 오프셋을 구하다z
또는 처음부터x
.
offsetof()
구조 부재의 간격띄우기
개요
#include <stddef.h>
size_t offsetof(type, member);
offsetof()
구조물 유형의 시작에서 필드 멤버의 간격띄우기를 반환합니다.
예
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
struct s {
int i;
char c;
double d;
char a[];
};
/* Output is compiler dependent */
printf("offsets: i=%ld; c=%ld; d=%ld a=%ld\n",
(long) offsetof(struct s, i),
(long) offsetof(struct s, c),
(long) offsetof(struct s, d),
(long) offsetof(struct s, a));
printf("sizeof(struct s)=%ld\n", (long) sizeof(struct s));
exit(EXIT_SUCCESS);
}
GCC로 컴파일하면 Linux에서 다음과 같은 출력을 얻을 수 있습니다.
offsets: i=0; c=4; d=8 a=16
sizeof(struct s)=16
질문한지 3년이 지났으니 완성도를 위해 답변을 덧붙입니다.
구조 부재의 오프셋을 얻는 기발한 방법은 다음과 같습니다.
printf("%p\n", (void*)(&((struct s *)NULL)->i));
예뻐 보이지 않고, 순수한 C(멤버의 오프셋을 얻을 수 있는, 구조에 대해 다른 것을 알지 못한 채)에서는 아무것도 생각할 수 없습니다.나는 믿습니다.offsetof
매크로는 이러한 방식으로 정의됩니다.
참고로, 이 기술은 리눅스 커널에서 사용됩니다.container_of
매크로:
http://lxr.free-electrons.com/source/scripts/kconfig/list.h#L18
자세한 설명은 다음 문서에서 확인할 수 있습니다.
http://radek.io/2012/11/10/magical-container_of-macro/
struct a foo;
printf("offset of k is %d\n", (char *)&foo.y.k - (char *)&foo);
printf("offset of i is %d\n", (char *)&foo.x.i - (char *)&foo);
foo.x.i
현장 참조i
구조상x
구조상foo
.&foo.x.i
필드의 주소를 제공합니다.foo.x.i
.유사하게,&foo.y.k
의 주소를 제공합니다.foo.y.k
;&foo
구조물의 주소를 알려줍니다.foo
.
주소 빼기foo
의 주소에서foo.x.i
에서 오프셋을 제공합니다.foo
로.foo.x.i
.
Gangadhar가 말했듯이, 당신은 사용할 수 있습니다.offsetof()
내가 준 포인터 산술 대신 매크로.하지만 포인터 산술을 먼저 이해하는 것이 좋습니다.
이미 제안했듯이, 당신은 다음을 사용해야 합니다.offsetof()
에서 매크로.<stddef.h>
그것은 오프셋을 생성합니다.size_t
가치.
예:
#include <stddef.h>
#include <stdio.h>
#include "struct_a.h" /* Header defining the structure in the question */
int main(void)
{
size_t off_k_y = offsetof(struct c, k);
size_t off_k_z = offsetof(struct a, y.k);
size_t off_i_x = offsetof(struct b, i);
size_t off_i_z = offsetof(struct a, x.i);
printf("k = %zu %zu; i = %zu %zu\n", off_k_y, off_k_z, off_i_x, off_i_z);
return 0;
}
출력 예:
k = 0 8; i = 0 0
오프셋을 찾기 위해, 이것이 우리가 할 수 있는 한 가지 방법입니다.
struct a{
struct b
{
int i;
float j;
}x;
struct c
{
int k;
float l;
}y;
}z;
int main(){
struct a* foo = &z;
printf("%d\n", foo); //address of z
printf("%d\n", &(foo->y)); //address of z.y
printf("%d\n", &( (&(foo->y))->k )); //address of z.y.k
int offset_k = (char*)&( (&(foo->y))->k ) - (char*)foo ;
printf("%d\n", offset_k);
return 0;
}
출력은 다음과 유사합니다.
4225552 //address of z
4225560 //address of z.y
4225560 //address of z.y.k
8 //offset
이 경우 inti가 구조체의 첫 번째 구성원이기 때문에 구조체의 기본 주소도 inti의 기본 주소가 됩니다.그렇지 않으면 비슷한 방법으로 inti의 간격띄우기를 계산할 수 있습니다.
int offset_i = (char*)&( (&(foo->x))->i ) - (char*)foo; //0 in this case
참고: 오프셋은 정의 방법에 따라 음수 또는 양수가 됩니다(기본 주소 또는 멤버 z.y.k와 관련된 경우).여기서, 이것은 구조체의 기본 주소와 관련하여 정의됩니다.
다음은 최신 버전과 이전 버전의 GNU C 모두에서 작동하는 일반적인 솔루션입니다.
<!-- language: C -->
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define GNUC_PREREQ(minMajor, minMinor) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((minMajor) << 16) + (minMinor))
#else
# define GNUC_PREREQ 0
#endif
#if GNUC_PREREQ(4, 0)
# define OFFSETOF(type, member) ((int)__builtin_offsetof(type, member))
#else
# define OFFSETOF(type, member) ((int)(intptr_t)&(((type *)(void*)0)->member) )
#endif
업데이트: 사용 예를 요청한 사용자가 있습니다.
struct foo {
int bar;
char *baz;
}
printf("Offset of baz in struct foo = %d\n",
OFFSETOF(foo, baz));
4장을 인쇄할 것인가, 만약.int
실행되는 시스템의 아키텍처에서 4바이트로 컴파일됩니다.
언급URL : https://stackoverflow.com/questions/18749349/finding-offset-of-a-structure-element-in-c
'programing' 카테고리의 다른 글
일치하는 값을 포함하는 해시 키를 찾는 방법 (0) | 2023.06.23 |
---|---|
Mongoose 인덱스를 만들지 않음 (0) | 2023.06.23 |
SQL 쿼리를 사용하여 Oracle 스키마 크기를 표시하는 방법은 무엇입니까? (0) | 2023.06.18 |
표에 SELECT 1이 있는 이유는 무엇입니까? (0) | 2023.06.18 |
최소 두 개의 날짜를 선택합니다. (0) | 2023.06.18 |