0

ここになぞなぞがあります。

次の C++ 関数があるとします。

template<uint8_t MASK>
uint8_t Foo(uint8_t val)
{
    uint8_t step = 0;
    uint8_t result = 0;
    if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;}
    if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;}
    //...etc...
    if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;}

    return result;
}

この関数をそのままインスタンス化すると (以下のすべての値は単なる値の例です):

uint8_t someval = Foo<0xAA>(44);

コンパイラは、コンパイル時に if() ステートメントの結果が何であるかを知っているため、Foo() の if ステートメントを最適化します。

これは良いことですが、C で同じことをしようとすると、ローカル変数stepが作成されるため問題が生じます。

stepがない場合は、次のように大きな #define を実行できます。

#define Foo(MASK, val) (\
    ((MASK & 0x01) ? (val & 0x01) : 0) | \
    ((MASK & 0x02) ? (val & 0x02) : 0) | \
    ...etc...
    ((MASK & 0x80) ? (val & 0x80) : 0) | \
    )

しかし、ステップでは、私は一種の行き詰まりに陥っています。ローカル変数を使用した C++ テンプレート関数の C で C++ テンプレートと同じ機能を取得するにはどうすればよいですか?

コンパイラはコンパイル時にMASKの値を認識しないため、インライン C 関数を使用することは答えではないことに注意してください。したがって、すべての比較は最適化されず、最終的にコンパイルされた出力の一部になります。

また、 #define を変更して結果の値を含めることも答えではないことに注意してください。これにより、「関数の」署名が変更されるためです。

そして最後に、このなぞなぞには答えがないかもしれないことを十分承知しています。

4

3 に答える 3

5

テンプレートが行うことをマクロに実行させます。インライン関数を作成する --

#define Foo(MASK, val) inline uint8_t Foo_##MASK(uint8_t val) \
{ \
   uint8_t step = 0; \
    uint8_t result = 0; \
    if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;} \
    if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;} \
    //...etc...
    if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;} \
\
    return result;\
}
于 2012-08-17T19:56:57.187 に答える
2

どうですか(GCCism):

#define Foo(MASK, val) ({ \
    uint8_t step = 0; \
    uint8_t result = 0; \
    if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;} \
    if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;} \
    //...etc...
    if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;} \
    result;})
于 2012-08-17T19:52:14.900 に答える
1

You are just making a false assumption

Note that using inline C functions is not an answer, as the compiler will not know at compile time the value of MASK, and thus all the comparisons will not be optimized and will accordingly be part of the final compiled output.

I just tested, gcc is able to inline everything without problem:

static inline
unsigned Foo(unsigned MASK, unsigned char val)
{
    unsigned char step = 0;
    unsigned char result = 0;
    if(MASK & 0x01) {result |= (val & 0x01) >> step; ++step;}
    if(MASK & 0x02) {result |= (val & 0x02) >> step; ++step;}
    //...etc...
    if(MASK & 0x80) {result |= (val & 0x80) >> step; ++step;}

    return result;
}

int main(int argc, char *argv[]) {
  return Foo(0x02, argc);

}

results in the following assembler for main:

main:
.LFB1:
    .cfi_startproc
    andl    $2, %edi
    movzbl  %dil, %eax
    ret
    .cfi_endproc
.LFE1:
    .size   main, .-main

and clang does functionally the same.

于 2012-08-17T22:04:17.310 に答える