2014-10-31 1 views
1

구조체를 큐에 넣고 배열에서 팝/푸시 기능을 제공하는 소스 파일이 있습니다.헤더가 #include (ed) 될 때마다 다르게 전처리 처리됩니다.

간략히하기 위해, queue.c 파일이 어떻게 보이는지에 대한 예가 있습니다. - 관련이없는 몇 가지 정의가 생략되었습니다. 헤더 파일 내에서

#include <stdint.h> 
#include <stdbool.h> 
#include <stdlib.h> 
#include "queue.h" 

queue_t queueCreate (void) { 
    queue_t newQueue; 
    newQueue.state = QUEUE_EMPTY; 
    newQueue.front = 0; 
    newQueue.count = 0; 
    return newQueue; 
} 

/* 
* Returns the first in from the queue passed to it if possible 
*/ 
enum STATE_QUEUE queuePop (queue_t *queue, queueElement_t *pop) { 
    // if queue isn't empty 
    if(!queue_isEmpty(queue)) { 
     // get element at front of queue 
     (*pop) = (*queue).queue[(*queue).front]; 

     // decrease count by 1 as element has been removed from queue 
     (*queue).count--; 

     // if front needs to wrap round the array 
     if((*queue).front == (QUEUE_SIZE - 1)) { 
      (*queue).front = 0; 
     } else { 
      (*queue).front++; 
     } 

     // 
     queueState(queue); 

     // return the popped element to the calling function 
     return QUEUE_OK; 
    } 
    return QUEUE_EMPTY; 
} 

queue.c

, 난 구조 내에서 구성원을 변경하는 몇 가지 유형과 사용하는 매크로를 선언합니다. 이 코드를 사용하면 #defines는 이러한 구조 내의 멤버를 지정합니다. 이들 매크로 정의 구조의 내용이 호출 소스 파일

헤더이

queue.h

#ifndef QUEUE_SIZE 
    #define QUEUE_SIZE 10 
    #define QUEUE_COUNT_TYPE BYTE 
#else 
    #ifndef QUEUE_COUNT_TYPE 
     #if QUEUE_SIZE > 255 
      #define QUEUE_COUNT_TYPE int 
     #else 
      #define QUEUE_COUNT_TYPE BYTE 
     #endif 
    #endif 
#endif 

    /* Queued types */ 
#ifndef QUEUE_TYPE 
    #define QUEUE_TYPE struct { \ 
          int data; \ 
         } 
#endif 

    /* Queue type definitions*/ 
    typedef QUEUE_TYPE queueElement_t; 

    typedef struct { 
     QUEUE_COUNT_TYPE front; 
     QUEUE_COUNT_TYPE count; 
     queueElement_t queue[QUEUE_SIZE]; 
    } queue_t; 

    /* Function Prototypes */ 
    queue_t    queueCreate (void); 

등 보이는 내 queue.c에 의해 참조되지 않습니다,하지만 정의되고 사용 가치가 아무것도 소스 파일을 호출하면 QUEUE_TYPE이 다시 정의되어 관련 구조체를 처리합니다.

이 헤더 파일을 프로젝트의 여러 소스 파일에서 사용할 때 queueElement_t의 정의를 변경하려면 #include #include를 #define과 함께 사용합니다.

함수 이름이 동일하기 때문에 형식 오류가 발생하지만 다른 인수 유형을 처리합니까? 아니면 제가 설명했던 방식으로이 작업을 할 수있는 방법이 있습니까?

TL; DR 난 내가 오류를 경험하게 될 것입니다, 명시 적으로 헤더 파일 내에서 액세스되지 않는 구조체의 멤버를 변경하는 매크로를 사용하여 내 프로젝트, 곳곳에 소스 파일에 헤더 파일을 포함하는 경우

+0

"* Header Guards *"의 정의와 사용 이유를 읽어보십시오. – alk

+0

@alk 감사합니다. 헤더 가드는 알고 있었지만 같은 범위 내에서 동일한 함수를 두 번 정의하지 않도록 충분히주의를 기울여도 추론이 계속 적용된다면 알 수 없습니다. – AustinGeorge

+0

이 함수는 queue_t queueCreate (void) {값을 반환합니다/구조체는 함수의 로컬 스택에 할당됩니다. 이것은 프로그래밍 노노입니다. 스택이 손상 될 가능성이 있기 때문입니다. 함수를 다음과 같이 변경하는 것이 훨씬 더 좋습니다. queue_t * queueCreate (void) {다음 함수 내 : this : queue_t newQueue; 다음과 같아야합니다 : queue_t * newQueue = malloc (sizeof queue_t); NULL이 아닌지 검사해야하며 다음 형식을 사용합니다. newQueue-> field = ..; 필드를 채 웁니다. 이제 호출자는 전체 queue_t 구조체 대신 포인터를 반환해야합니다. – user3629249

답변

1

귀하의 특별한 경우 : 예. 특정 구조를 리턴으로 사용할 것으로 예상되는 함수가 있기 때문입니다. 따라서 유형 정의가 다른 두 모듈의 구조를 사용하려고하면 사용중인 플랫폼에서 ABI와 관련된 매우 흥미로운 문제점을 발견하게됩니다.

그러나 C++의 템플릿과 비슷한 기능을하는 매크로 만 사용할 수 있습니다. 작은 예 :

#define QUEUE_TYPE(element, size) struct { int front, count; type queue[size]; } 
#define QUEUE_INIT(queue) queue.front = queue.count = 0; 
#define QUEUE_SIZE(queue) sizeof(queue.queue)/sizeof(queue.queue[0]) 
#define QUEUE_PUSH(queue,val) \ 
    if (queue.front < QUEUE_SIZE(queue)) queue.queue[queue.front++] = val; 
... 

struct { 
    QUEUE_TYPE(int,10) member; 
} my_var; 
... 
QUEUE_INIT(my_var.member); 
QUEUE_PUSH(my_var.member, 10) 
+0

아, 그건 의미가 있습니다.'queue.h '의 다른 호출이 결코 같은 범위에 있지 않을 때 여전히 적용됩니까? – AustinGeorge

+0

@AustinGeorge 예. 기호 (예 : function)를 정의하기 때문에 전역 범위에서 볼 수 있습니다. 모든 함수가 정적으로 헤더 내부에 정의되면 전역 심볼이 제거되지만 모듈 범위 내에서 매크로를 여러 번 재정의 할 수 있습니다. –

+0

감사합니다. 나는 이것이 과거에 pic micros에 대해서만 c를 사용했다는 것을 고려하여 범위를 다루는 경험이 부족하다는 데서 비롯된 것이라고 생각한다. 큐브를 호출 할 때 큐 요소 구조의 차이점을 허용하기 위해 모든 요소 처리 로직을 호출 모듈에서 큐 모듈로 옮길 수 있습니까? 또한 요소가 팝업 될 때 동일한 기능을 유지하려면 ID가 전역 범위에서 변수를 변경할 수 있어야합니다. 이 전역 변수에 대한 각 요소에 할당 된 포인터를 사용하여이 작업을 수행 할 수 있을까요? – AustinGeorge

관련 문제