Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 条件位设置_C_Security_Optimization_Conditional - Fatal编程技术网

C 条件位设置

C 条件位设置,c,security,optimization,conditional,C,Security,Optimization,Conditional,根据我的小型研究,以下两个函数是等效的(从性能角度来看),因为即使是非常轻微的优化(-O1)也会产生相同的汇编代码 代码1: #define BIT_N (10) extern unsigned int isBitSet; unsigned int Foo() { unsigned int res1 = 0; if (isBitSet) { res1 |= ( 1u << BIT_N ); } return res1;

根据我的小型研究,以下两个函数是等效的(从性能角度来看),因为即使是非常轻微的优化(
-O1
)也会产生相同的汇编代码

代码1:

#define BIT_N (10)

extern unsigned int isBitSet;

unsigned int Foo() {
    unsigned int res1 = 0;

    if (isBitSet)
    {
        res1 |= ( 1u << BIT_N );
    }

    return res1;
}

我个人更喜欢代码2的C版本,它看起来更干净。但它是否和代码1一样安全?因为我看到了一些潜在的陷阱,比如如果
isBitSet
的类型是
int
BIT\N
31,那么代码
res1=(!!isBitSet)运算符
返回的类型是
int
,所以可以得到UB。(
isBitSet
类型的签名性并不重要)

根据N1570,6.5.7位移位运算符:

  • E1的结果(值为
    0
    1
    )。后续的。例如,假设一个32位
    int
    和两个补码,如果
    !!isBitSet==1
    位N>=31
    (因为随后1位被移入或移出符号位),就会发生这种情况.因此,你提到的潜在陷阱确实是一个

    除此之外,代码定义良好,两个函数具有相同的行为。因此,只要避免上述未定义行为的条件,第二个函数就相当于第一个函数

    也就是说,第一种可能更可取,因为它更明确地表达了它的意图(因此更容易阅读),并且不可能有未定义的行为

    因为我看到了一些潜在的陷阱,比如isBitSet的类型是int和BIT_N 31

    您已经遇到了另一个陷阱,即假定
    的类型是位集
    重要的。C中的所有“逻辑”运算符,如
    都返回值为1或0的类型
    int


    因此表达式
    (!!isBitSet)如果开始时
    res1=5
    ,“代码1和代码2的反汇编是相同的”。如果是,则编译器已损坏。代码1使用|=,代码2使用=@JeremyP,但不会更改结果。+请参阅我对的注释tilz0R@JeremyP我修改了代码,使其具有相同的
    |=
    。但这并不是本文的重点。我发现
    if(isBitSet)
    (.ISBITSET)。你应该考虑让人们读代码比编译器更容易(这似乎是无论如何得到的)。<代码> ISBITSET  >的类型并不重要。
    
    #define BIT_N (10)
    
    extern unsigned int isBitSet;
    
    unsigned int Foo() {
        unsigned int res1 = 0;
    
        res1 |= ( (!!isBitSet) << BIT_N );
    
        return res1;
    }
    
    Foo():
        mov     edx, DWORD PTR isBitSet[rip]
        xor     eax, eax
        test    edx, edx
        setne   al
        sal     eax, 10
        ret
    
    res1 |= (unsigned)(!!isBitSet) << BIT_N;
    
    ((!!isBitSet) << BIT_N) + UINT16_C(something)
    
    uint32_t Foo (void) 
    { 
      uint32_t result;
    
      if(isBitSet)
      {
        result = 1u << BIT_N;
      }
      else
      {
        result = 0;
      }
    
      return result;
    }
    
    uint32_t Foo (void) 
    { 
      return isBitSet ? 1u<<BIT_N : 0;
    }