2015-01-22 2 views
5

나는 다음과 같은 문제에 대해 생각하고있다. 어떤 종류의 룩업 테이블을 사용하는 프로그램으로 마이크로 컨트롤러 (AVR 메가 타입이라고하자)를 프로그램하고 싶다.GCC 컴파일 타임에 함수를 평가하는 방법은 무엇입니까?

첫 번째 시도는 별도의 파일에서 테이블을 찾아 다른 스크립팅 언어/프로그램/....을 사용하여 만듭니다.이 경우 C에 필요한 소스 파일을 만드는 데 상당한 노력이 있습니다.

제 생각에는 전처리 기와 컴파일러를 사용하여 처리 할 생각이었습니다. 나는 (단지 예를 들어) 사인 값의 테이블과이를 구현하려고 :이 코드를 컴파일하면

#include <avr/io.h> 
#include <math.h> 

#define S1(i,n) ((uint8_t) sin(M_PI*(i)/n*255)) 
#define S4(i,n) S1(i,n), S1(i+1,n), S1(i+2,n), S1(i+3,n) 

uint8_t lut[] = {S4(0,4)}; 

void main() 
{ 
    uint8_t val, i; 

    for(i=0; i<4; i++) 
    { 
     val = lut[i]; 
    } 
} 

내가 sin 기능에 대한 경고를 얻을. 조립시에는 .data 섹션에는 아무 것도 없습니다. 세 번째 줄에 sin을 제거하면 어셈블리에서 데이터를 가져옵니다. 분명히 모든 정보는 컴파일 할 때 사용할 수 있습니다.

내가 원하는 것을 성취 할 수있는 방법이 있는지 말해 줄 수 있습니까? 컴파일러는 가능한 많은 값을 오프라인으로 계산합니까? 또는 외부 스크립트/프로그램/...을 사용하여 테이블 항목을 계산하고이를 #include d가 될 별도의 파일에 추가하는 가장 좋은 방법은 무엇입니까?

+1

"꽤 많은 노력을."- 좋은 스크립팅 언어? 확실하게 C로 문제를 공격하는 것보다 작다. –

+0

C++ 11 (C++ 14로 개선됨)은 컴파일 타임에 함수를 실행하기위한 컴파일러의 힌트로'constexpr'을 가진다. – johannes

+0

@ johannes :'constexpr'은 이점이 없습니다. 컴파일 타임에 평가되는 표현식을 단지 _allows_ (예를 들어, 열거 형에 할당하여 런타임에서 동일한 소스 파일의 다른 위치에서 재평가하는 것을 방지하지는 않습니다.). 그것은 아무 것도 강요하거나 암시하지 않습니다. 즉, 내 GCC는 OP의 코드 스 니펫을 컴파일 룩업 테이블 (특별한 춤을 사용하지 않고)으로 최적화합니다. – Damon

답변

4

여기에 일반적인 문제는되지 상수 표현 자체 그리고 당신이 필요 정적 저장 기간의 배열을 초기화하고 같은 sin 호출, C 언어의 규칙에 따라,이 초기화 사실상 불법을 만드는 것입니다 그. 이것은 배열이 .data 섹션에없는 이유를 설명합니다.

C11 일정한 발현 번역보다는 런타임 동안 평가 될 수 있으며, 따라서 임의의 장소에서 이용 될 수있다

(N1570) §6.6/2,3- 정수 식 (강조 광산) 그 상수는 일 수 있습니다.

상수 표현 하여야한다하지 할당, 증가, 감소, 가되지 evaluated.115)

있는 표현식에 포함 있는 경우를 제외하고, 쉼표 사업자을 함수 호출, 또는 포함 그러나 @ ShafikYaghmour의 설명에 따르면 GCC는 sin 함수 호출을 내장 된 대응 함수 (-fno-builtin 옵션이없는 경우)로 대체 할 것이며 이는 상수 표현으로 처리 될 가능성이 높습니다.6.57 Other Built-in Functions Provided by GCC에 따르면

GCC는 포함 내장 표준 C 라이브러리의 많은 기능의 버전. __builtin_이 붙은 버전은 -fno-builtin 옵션을 지정하더라도 항상 은 C 라이브러리 함수와 동일한 의미로 취급됩니다.

+1

이것은 현재 [gcc가 수학 내장 함수를 상수 표현식으로 취급하기 때문에] (http://stackoverflow.com/q/27744079/1708801),'-fno-builtin'을 사용하면'gcc'를 사용하여 유사한 코드가 실패하지만 그렇지 않은 경우에만 경고를 생성합니다. –

+0

@ShafikYaghmour : 그럼 왜 해체에 데이터가 없습니다. 나는 완전히 확신 할 수 없다. 만약 내가 데이터에 접근하려고하면 어떤 일이 일어날 지 ... –

+0

@ChristianWolf : 당신은'__builtin_sin'에 의해 그것을 강제 할 수 있지만 Shafik에 동의한다. 어쩌면 당신은 그것을 지원하지 않는 avr-gcc 포트를 사용하고 있습니까? –

2

시도한 것은 C 언어의 일부가 아닙니다. 이 같은 상황에서,이 패턴 다음 코드를 작성했습니다 :

#if GENERATE_SOURCECODE 
int main (void) 
{ 
    ... Code that uses printf to write C code to stdout 
} 
#else 
    // Source code generated by the code above 
    ... Here I paste in what the code above generated 

    // The rest of the program 
#endif 

당신이 그것을 변경해야 할 때마다, 당신은 정의 GENERATE_SOURCECODE와 코드를 실행하고 출력에 붙여 넣습니다. 코드가 자체 포함되어 있고 생성 된 코드가 변경되면 생성 된 출력 만 변경됩니다.

+0

을 사용할 것입니다. – Joshua

+0

이것은 교차 컴파일이라는 의미에서 최적이 아닙니다. 따라서 그것은 괜찮을지도 모릅니다. 모든 헤더 파일을 교환해야하므로'# if' 블록 내부에서 두 개의 다른 파일을 유지하는 것보다 더 많은 노력을 기울일 것 같습니다. 미안해, 미안해. –

2

우선, 이것이 가치가 있는지 여부를 (아마도 실험을 통해) 평가해야한다는 것은 말할 필요도 없습니다. 룩업 테이블은 데이터 크기와 프로그래머 노력을 증가 시키지만 필요한 런타임 실행 속도를 제공하지 않을 수도 있습니다.

아직도 그것을하고 싶다면 C 전처리 기는 반복 또는 재귀 기능이 없으므로 직접 처리 할 수 ​​없다고 생각합니다.

가장 확실한 방법은 C 또는 다른 언어로 프로그램을 작성하여 테이블의 C 소스를 인쇄 한 다음 해당 파일을 전처리기를 사용하여 프로그램에 포함시키는 것입니다. make과 같은 도구를 사용하는 경우 테이블 파일을 생성하고 .c 파일을 해당 파일에 종속시키는 규칙을 만들 수 있습니다. 당신은 당신이 결코이 테이블을 변경하려고하지 않습니다 확신하는 경우

한편

, 당신은 한 번 생성하고 그냥 붙여 넣기하는 프로그램을 작성할 수

관련 문제