如何在C

时间:2016-10-22 12:45:39

标签: c

前置条件:

  1. 我不能使用malloc。
  2. 错误将在两个字节内发生,这意味着我可以逐字搜索。
  3. 我的CPU是32位ARM11,在此期间没有操作系统。
  4. 前两个字节很重要,如果前两个字节是0x00,则表示所有其余字节应为0x00。
  5. 如果前两个字节是0xFF,则所有其余字节应为0xFF。
  6. 如果前两个字节不是0x0000和0xFFFF,我只是报告错误,不需要比较其余的。
  7. 我读取256Kbyte块数据,它应该只有两种状态:

    1. 全部为0xFF
    2. 全部为0x00
    3. 但是,某些数据可能会更改为不可预测的值。我需要找到它们。我可以一个字节一个字节地搜索它,但看起来太慢了,所以我决定用二分法来做它 - 看起来像:

      1. 将读出的数据分成相等的一半,然后进行比较。
      2. 如果两者都不等于全0或F,则意味着数据在两侧都是腐败的,我只需要找到最早的数据,所以我应该放弃第二部分,然后再将第一部分分开。如果只有一方有问题,那就放弃好的方面,专注于有问题的on.e
      3. 循环以上的想法
      4. 似乎在17次之后,应该找到重点。
      5. 如何将代码写入循环?我是否需要17种不同大小的参考静态数据并使用memcmp

        我目前的代码如下:

        unsigned char gReferData1[2] = {0xFF, 0xFF};
        unsigned char gReferData2[2] = {0x00, 0x00};
        
        int main(void)
        {
            int i = 0, result1 = 0, result2 =0;
        
            read_somewhere(readBuff, sizeof(readBuff)); //read out data
        
            //first test first two bytes
            result1 = memcmp(gReferData1, readBuff, 2); //test if 0xFFFF
            result2 = memcmp(gReferData2, readBuff, 2); //test if 0x0000
            if(result1 == 0)
            {
                // means all rest data should be 0xFF 
                for(i=2; i<(0x40000/2); i++)
                {
                    result1 = memcmp(gReferData1, readBuff + offet, 2); //test if 0xFFFF
                    if(result1 != 0)
                    {
                        //means find
                        // do error handle
                    }
                    offset+=2;
                }
            }
            else if(result2 == 0)
            {
                // means all rest data should be 0x00
                for(i=2; i<(0x40000/2); i++)
                {
                    result2 = memcmp(gReferData2, readBuff + offet, 2); //test if 0x0000
                    if(result2 != 0)
                    {
                        //means find
                        // do error handle
                    }
                    offset+=2;
                }
            }
            else
            {
                //just error
                // do error handle
            }
        
            return 0;
        }
        

2 个答案:

答案 0 :(得分:3)

为了在随机位置找到缺陷,您需要至少检查一次每个字节。对于此,没有比O(n)更快的算法。

但是,您提出的算法需要多次检查每个字节。为了“将读出数据分成相等的一半,然后进行比较”,您必须读取每个字节。这就是memcmp将在内部执行的操作:从头到尾遍历两个内存段,直到出现异常。这不是魔术。它不能比用简单的循环更有效率地做到这一点。

可能加快速度(测试并测量它!)的优化可能是不是逐字节地遍历数据数组,而是以sizeof(long)为步长然后在比较之前将该细分投放到long。这利用了许多32位CPU(不是全部,测试和测量它!)的事实,比较两个32位值并不需要花费更多时间来比较两个8位值。

答案 1 :(得分:2)

您需要检查该缓冲区的无字节是否具有非法状态,因此您必须至少检查一次每个字节。

在大多数系统上,跳转是昂贵的,顺序读取字节比任何东西都便宜。因此,我可以使用更多顺序读取。

您可能尝试做的一件事是按顺序读取整个缓冲区,并将每个条目与前一个条目的条目进行比较,&#34;条目&#34;是一个字节或16,32或64位字,取决于哪个更快:

DATATYPE previous = *bufptr;
for (i = 1; i < (length of buffer divided by DATATYPE size); i++) {
    if (previous != *(bufptr++)) {
        break;
    }
}
if (i != (length of buffer divided by DATATYPE size)) {
    // There has been an error.
}
// Verify that previous is either 0 or the appropriate number of 0xF's.

另一种可能性是在缓冲区的前半部分和缓冲区的后半部分之间运行memcmp(),然后(仅适用于lols)验证第一个字节确实是0x00或0xFF。如果两半中相同相对位置的两个位同时翻转,则会失败。这有多大可能?它还取决于硬件(假设缓冲区是两个完全相同的芯片,由相同的宇宙射线以完全正确的角度进行串联......)。

根据架构,使用的编译器和优化,任一解决方案可能会变得更快;可能不是那么多。