2009-09-21 2 views
7

C/C++에이 매크로 offsetof이 있습니다.이 매크로를 사용하면 POD 구조에있는 구성원의 주소 오프셋을 가져올 수 있습니다. C FAQ에서 예를 들면 다음과 같습니다합법적 인 C/C++의 offsetof 매크로 사용

struct foo { 
int a; 
int b; 
}; 

struct foo; 

/* Set the b member of foo indirectly */ 
*(int *)((char *)foo + offsetof(b)) = 0xDEADBEEF; 

지금 이것은 단지 나에게 악을 보인다 나는이 매크로의 많은 합법적 인 사용을 볼 수 없습니다.

나는이 내장 된 구조 부모 개체의 주소를 얻기를위한 리눅스 커널의 container_of 매크로 소용입니다 본 한 합법적 예 :

/* get the address of the cmos device struct in which the cdev 
    structure which inode points to is embedded */ 
struct cmos_dev *cmos_devp = 
    container_of(inode->i_cdev, struct cmos_dev, cdev); 

이 매크로에 대한 합법적 어떤 다른 용도가 있습니까? 당신은 이 아니며이 매크로를 사용하십니까?

EDIT 지금까지 다른 질문에 대한 this answer은 제가 지금까지 본 최고의 질문입니다.

+0

첫 번째 사용은 C에서 합법적이지만 C++에서 포인터를 사용하면 거의 필요가 없습니다. –

+1

여기에 대한 다른 질문이 있습니다 : http://stackoverflow.com/questions/400116/what-is-the-purpose-and-return-type-of-the-builtinoffsetof-operator –

답변

4

음 ... C에서는 데이터 구조를 설명하는 데 코드가 필요한 모든 장소에서 매우 유용합니다. 예 : 옵션을 설정하기 위해 런타임 생성 GUI를 수행한다.

이 작업은 다음과 같습니다. 옵션이 필요한 명령은 옵션을 포함하는 로컬 구조를 정의한 다음 해당 필드를 나타내는 offsetof을 사용하여 구조를 GUI를 생성하는 코드에 설명합니다. 절대 주소가 아닌 오프셋을 사용하면 GUI 코드가 구조체의 인스턴스와 함께 작동 할 수 있습니다.

예를 들어 (시도했지만) 재빨리 스케치하기가 어렵지만 주석에 예제가 순서대로 있음을 나타내므로 다시 시도 할 것입니다.

"명령"이라고하는 독립형 모듈이 있으며 응용 프로그램에서 일부 동작을 구현한다고 가정합니다. 이 명령에는 그래픽 사용자 인터페이스를 통해 사용자에게 노출되어야하는 일반 동작을 제어하는 ​​여러 옵션이 있습니다. 이 예의 목적을 위해, 애플리케이션이 파일 관리자이고, 명령이 예를 들어, "부".

아이디어는 복사 코드가 하나의 C 파일과 GUI 코드에 있고 GUI 코드가 복사 명령 옵션을 "지원"하기 위해 하드 코딩 될 필요가 없다는 것입니다. 대신, 우리가 같이 복사 파일의 옵션을 정의 :

struct copy_options 
{ 
    unsigned int buffer_size;  /* Number of bytes to read/write at a time. */ 
    unsigned int copy_attributes; /* Attempt to copy attributes. */ 
    /* more, omitted */ 
}; 

static struct copy_options options; /* Actual instance holding current values. */ 

그런 다음, 복사 명령은 GUI 모듈의 구성 설정을 등록합니다 다음

void copy_register_options(GUIModule *gui) 
{ 
    gui_command_begin(gui, "Copy"); 
    gui_command_add_unsigned_int(gui, "Buffer size", offsetof(struct copy_options, buffer_size)); 
    gui_command_add_boolean(gui, "Copy attributes", offsetof(struct copy_options, copy_attributes)); 
    gui_command_end(gui); 
} 

,의는 사용자가 요청 가정 해 봅시다 copy 명령의 옵션을 설정하십시오. 우리는 먼저, 현재의 옵션을 복사 할 수 있습니다 취소를 지원하고,이 명령의 옵션 편집에 적합한 실행 시간에 구축 된 대화 지주 컨트롤의 GUI 모듈을 물어 : 물론

void copy_configure(GUIModule *gui) 
{ 
    struct copy_options edit = options; 

    /* Assume this opens a modal dialog, showing proper controls for editing the 
    * named command's options, at the address provided. The function returns 1 
    * if the user clicked "OK", 0 if the operation was cancelled. 
    */ 
    if(gui_config_dialog(gui, "Copy", &edit)) 
    { 
    /* GUI module changed values in here, make edit results new current. */ 
    options = edit; 
    } 
} 

를이 코드는 가정 설정은 순수한 값 유형이 될 수 있으므로 간단한 구조 지정을 사용하여 구조체를 복사 할 수 있습니다. 동적 문자열도 지원하는 경우 복사를 수행하는 함수가 필요합니다. 구성 데이터에 대한 모든 문자열은 구조체에 정적으로 배열 된 char 배열로 표현하는 것이 가장 좋을 것입니다.

GUI 모듈이 오프셋으로 표현 된 각 값의 수명을 알 수 있다는 사실을 통해 대화 상자 기능에 임시 온 스택 복사본을 제공 할 수 있습니다. 우리가 대신 GUI 모듈을 각 필드에 대한 직접 포인터로 설정했다면 이것은 유연성이 훨씬 떨어질 수 있습니다.

+0

포인터를 사용하지 않을까요? 또한 'struct의 모든 인스턴스와 작업'할 수 있습니까? –

+0

@ 로버트 : 하나만 사용하기 때문에; 네가 포인터를 준 포인터. 오프셋을 사용하여 구조체를 GUI 작성 코드에 다시 설명하지 않고 동일한 구조체의 두 인스턴스에 대한 GUI를 작성할 수 있습니다. – unwind

+0

나는 어떤 이유로 든 그것을 얻지 못할뿐입니다. 귀하의 게시물에 간단한 코드 예제를 추가 할 수 있습니까? –

1

오프셋은 일반적으로 보통 C로 작성해야하지만 때때로 "기타"기능이 필요한 장치 드라이버 프로그래밍에 비교적 자주 사용됩니다. 일부 구조체에 대한 포인터를 가져 오는 콜백 함수가 있다고 가정합니다. 이제이 구조 자체가 다른 더 큰 "외부"구조의 멤버입니다. "offsetof"로 설정하면 "내부"멤버에 만 액세스 할 때 "외부"구조의 멤버를 변경할 수 있습니다. 이 같은

뭔가 : 당신이 구조체 A가 구조체 B. 의 한 부분으로 그러나 "some_API_callback_func"에 대한 프레임 워크가 잘 설명되어 많은 장소에 있지 사용하는 것이 가능성이있는 경우 물론

struct A 
{ 
int a1; 
int a2; 
}; 

struct B 
{ 
int b1; 
int b2; 
A a; 
}; 

void some_API_callback_func(A * a) 
{ 
//here you do offsetof 
//to get access to B members 
} 

이 위험하다 이 잘 작동합니다.

+0

고마워,하지만 이것은 정확히 리눅스 커널의 container_of 매크로와 관련해서 이미 설명했다. –

2

는 기본적으로, 당신은 C++에서 멤버 (T::*)에 대한 포인터와 함께 할 거라고 아무것도 ++ 이러한 이유로 C에서 offsetof의 사용에 대한 좋은 후보가, offsetof는 C 훨씬 드물다입니다. 구조체에 대한

  • 세미 일반적인 분류 기능 :

    지금이 그래서 여기에 몇 가지 예입니다, 물론 약간의 원형이다. qsort은 이상적인 콜백을 사용하지 않습니다. 종종 한 멤버의 자연 순서에 따라 정렬 할 필요가 있습니다. 세 번째로 int 구조입니다. 가상의 qsort_int은이 목적으로 offsetof 인수를 허용 할 수 있습니다.

  • 마찬가지로, 당신은 내가 임베디드 시스템에 사용되는 한 가지 방법 int out[10]; extract(int, &MyFoo[0], &MyFoo[10], out, offsetof(struct Foo, Bar));
5

하나 말할 수있는 매크로 extract 등을 쓸 수있다이다 나는 비 휘발성의 레이아웃을 나타내는 구조체가 어디 메모리 (예 : EEPROM),하지만 어디 실제로 RAM 에서이 구조체의 인스턴스를 만들고 싶지 않아요. 다양한 멋진 매크로 트릭을 사용하여 EEPROM에서 특정 필드를 읽고 쓸 수 있습니다. 여기서 offsetof는 구조체 내의 필드 주소 계산 작업을 수행합니다.

'악마'와 관련하여 전통적으로 'C'프로그래밍, 특히 리소스가 제한된 플랫폼에서 많이 행해지는 것들이 현대 컴퓨팅의 고급스러운 주변에서 볼 때 악의적 인 해커처럼 보임을 기억해야합니다 .

5

offsetof() 하나 개의 합법적 인 사용은 유형의 정렬을 결정하는 것입니다 : 객체의 정렬을 필요로하는 약간 낮은 수준이 될 수

#define ALIGNMENT_OF(t) offsetof(struct { char x; t test; }, test) 

을하지만, 어떤 경우에 나는 이것을 생각 하는데요 정당한 사용.

관련 문제