programing

c에서 구조 요소의 간격띄우기 찾기

subpage 2023. 6. 18. 16:02
반응형

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

반응형