program story

컴파일 타임에 C 문자열의 길이를 계산합니다.

inputbox 2020. 9. 19. 11:08
반응형

컴파일 타임에 C 문자열의 길이를 계산합니다. 이것은 정말로 constexpr입니까?


컴파일 타임에 문자열 리터럴의 길이를 계산하려고합니다. 이를 위해 다음 코드를 사용하고 있습니다.

#include <cstdio>

int constexpr length(const char* str)
{
    return *str ? 1 + length(str + 1) : 0;
}

int main()
{
    printf("%d %d", length("abcd"), length("abcdefgh"));
}

모든 것이 예상대로 작동하고 프로그램은 4와 8을 인쇄합니다. clang에 의해 생성 된 어셈블리 코드는 결과가 컴파일 시간에 계산됨을 보여줍니다.

0x100000f5e:  leaq   0x35(%rip), %rdi          ; "%d %d"
0x100000f65:  movl   $0x4, %esi
0x100000f6a:  movl   $0x8, %edx
0x100000f6f:  xorl   %eax, %eax
0x100000f71:  callq  0x100000f7a               ; symbol stub for: printf

내 질문 : length함수가 컴파일 시간에 평가된다는 것이 표준에 의해 보장 됩니까?

이것이 사실이라면 컴파일 타임 문자열 리터럴 계산의 문이 방금 열렸습니다 ... 예를 들어 컴파일 타임에 해시를 계산할 수 있습니다.


상수 표현식은 컴파일 시간에 평가된다는 보장이 없습니다. C ++ 표준 섹션 5.19 상수 표현식 초안 의 비 규범 적 인용 만 있습니다.

[...]> [참고 : 변환 중에 상수 표현식을 평가할 수 있습니다 .—end note]

결과를 constexpr변수에 할당하여 컴파일 타임에 평가되는지 확인할 수 있습니다. Bjarne Stroustrup의 C ++ 11 참조 에서 확인할 수 있습니다. ( emphasis mine ) :

컴파일 타임에 표현식을 평가할 수있을뿐만 아니라 컴파일 타임에 표현식을 평가 하도록 요구할 수 있기를 원합니다 . 변수 정의 앞의 constexpr은 그렇게합니다 (그리고 const를 의미합니다) :

예를 들면 :

constexpr int len1 = length("abcd") ;

Bjarne Stroustrup은이 isocpp 블로그 항목 에서 컴파일 시간 평가를 보장 할 수있는시기에 대한 요약을 제공하며 다음 과 같이 말합니다.

[...] 정답은-Herb에서 언급했듯이-표준에 ​​따라 constexpr 함수는 상수 표현식으로 사용되지 않는 한 컴파일러 시간 또는 런타임에 평가 될 수 있으며,이 경우 컴파일시 평가되어야합니다. -시각. 컴파일 타임 평가를 보장하려면 상수 표현식이 필요한 곳에 사용하거나 (예 : 배열 바인딩 또는 케이스 레이블로)이를 사용하여 constexpr을 초기화해야합니다. 나는 자존심이 강한 컴파일러가 내가 원래 말했던 것을 할 수있는 최적화 기회를 놓치지 않기를 바란다 : "모든 인수가 상수 표현식이라면 constexpr 함수는 컴파일 타임에 평가된다."

따라서 이것은 컴파일 타임에 평가되어야하는 두 가지 경우에 대해 설명합니다.

  1. 상수 표현식이 필요한 곳에 사용하십시오. 이것은 shall be ... converted constant expression또는 구문 shall be ... constant expression이 사용되는 초안 표준 ( 예 : 배열 바운드)의 어느 곳에서나 사용됩니다.
  2. constexpr위에서 설명한대로 초기화하는 데 사용하십시오 .

constexpr함수 호출 핵심 상수 표현식을 생성 하는지 아니면 단순히 최적화되고 있는지 확인하는 것은 정말 쉽습니다 .

상수 표현식이 필요한 컨텍스트에서 사용하십시오.

int main()
{
    constexpr int test_const = length("abcd");
    std::array<char,length("abcdefgh")> test_const2;
}

참고로 최신 컴파일러 (예 : gcc-4.x) strlen는 일반적으로 내장 함수 로 정의되기 때문에 컴파일 타임에 문자열 리터럴에 대해 수행 합니다 . 최적화가 활성화되지 않았습니다. 결과가 컴파일 시간 상수는 아니지만.

예 :

printf("%zu\n", strlen("abc"));

결과 :

movl    $3, %esi    # strlen("abc")
movl    $.LC0, %edi # "%zu\n"
movl    $0, %eax
call    printf

Let me propose another function that computes the length of a string at compile time without being recursive.

template< size_t N >
constexpr size_t length( char const (&)[N] )
{
  return N-1;
}

Have a look at this sample code at ideone.


There is no guarantee that a constexpr function is evaluated at compile-time, though any reasonable compiler will do it at appropriate optimization levels enabled. On the other hand, template parameters must be evaluated at compile-time.

I used the following trick to force evaluation at compile time. Unfortunately it only works with integral values (ie not with floating point values).

template<typename T, T V>
struct static_eval
{
  static constexpr T value = V;
};

Now, if you write

if (static_eval<int, length("hello, world")>::value > 7) { ... }

you can be sure that the if statement is a compile-time constant with no run-time overhead.


A short explanation from Wikipedia's entry on Generalized constant expressions:

The use of constexpr on a function imposes some limitations on what that function can do. First, the function must have a non-void return type. Second, the function body cannot declare variables or define new types. Third, the body may contain only declarations, null statements and a single return statement. There must exist argument values such that, after argument substitution, the expression in the return statement produces a constant expression.

Having the constexpr keyword before a function definition instructs the compiler to check if these limitations are met. If yes, and the function is called with a constant, the returned value is guaranteed to be constant and thus can be used anywhere a constant expression is required.

참고URL : https://stackoverflow.com/questions/25890784/computing-length-of-a-c-string-at-compile-time-is-this-really-a-constexpr

반응형