2017-10-17 172 views
-2

我想在C中做一些操作。直到现在,我所做的一切都是正确的,但最终测试表明存在错误。对我来说功能看起来不错,但是......输出与预期不同。位操作出错C

#include <stdint.h> 

#include "PETER_interface.h" 

const int BITS_IN_BYTE = 8; 
static int g_capacity = 0; 
static int g_size = 0; 
static container_id_t indexOfTable = 0; 

uint8_t* storages[4] = {0 ,0 ,0 ,0}; 

err_t PETER_new(container_id_t* id, int num_of_bits) { 
    storages[indexOfTable] = (uint8_t*)(malloc((num_of_bits/BITS_IN_BYTE) 
    + (num_of_bits % BITS_IN_BYTE) ? 1 : 0)); 

    g_capacity = num_of_bits; 
    g_size = ((num_of_bits/BITS_IN_BYTE) + (num_of_bits % BITS_IN_BYTE) ? 
1 : 0); 

    *id = indexOfTable; 

    indexOfTable++; 

    return E_OK; 
} 

err_t PETER_resize(container_id_t id, int bit) { 
    return E_NOT_IMPLEMENTED; 
} 

err_t PETER_delete(container_id_t id) { 
    return E_NOT_IMPLEMENTED; 
} 

err_t PETER_deleteAll() { 
    return E_NOT_IMPLEMENTED; 
} 

err_t PETER_set(container_id_t id, int bit) { 
    uint8_t temp = *(storages[id])/BITS_IN_BYTE; 

    temp |= (1 << (bit % BITS_IN_BYTE)); 

    *(storages[id]) = temp; 

    return E_OK; 
} 

err_t PETER_clear(container_id_t id, int bit) { 
    uint8_t temp = *(storages[id])/BITS_IN_BYTE; 

    temp &= ~(1 << (bit % BITS_IN_BYTE)); 

    *(storages[id]) = temp; 

    return E_OK; 
} 

err_t PETER_invert(container_id_t id, int bit) {  
    uint8_t temp = *(storages[id])/BITS_IN_BYTE; 

    temp ^= (1 << (bit % BITS_IN_BYTE)); 

    *(storages[id]) = temp; 

    return E_OK; 
} 

err_t PETER_capacity(container_id_t id, int *capacity) { 
    *capacity = g_capacity; 

    return E_OK; 
} 

err_t PETER_storageSize(container_id_t id, int *size) { 
    *size = g_size; 

    return E_OK; 
} 

err_t PETER_get(container_id_t id, int flag_no, int *return_value) {  
    *return_value = (*(storages[id]) >> (flag_no % BITS_IN_BYTE)) & 1; 

    return E_OK; 
} 

我的测试是这样的:

int ok = 1; 

    const int size = 8; 
    container_id_t id; 
    int val; 


    OK( new(&id,size),   E_OK ); 

    OK( capacity(id, &val), E_OK ); 
    OK( val, size); 

    OK( storageSize(id, &val), E_OK ); 
    OK( val, 1); 

    printf("storageSize: %d\n", val); 

    OK( set(id, 4),   E_OK ); 
    OK( get(id, 4, &val),  E_OK ); 

    printf("set: %d\n", val); 

    OK( val, 1); 

    OK( clear(id, 4),   E_OK ); 
    OK( get(id, 4, &val),  E_OK ); 

    printf("clear: %d\n", val); 

    OK( val, 0); 

    OK( invert(id, 4),   E_OK );  
    OK( get(id, 4, &val),  E_OK ); 

    printf("invert: %d\n", val); 

    OK( val, 1); 

    OK( invert(id, 4),   E_OK ); 
    OK( get(id, 4, &val),  E_OK ); 

    printf("invert: %d\n", val); 

    OK( val, 0); 


    // not yet implemented 
    OK( resize(id, 2*size),E_NOT_IMPLEMENTED ); 
    OK( delete(id),  E_NOT_IMPLEMENTED ); 
    OK( deleteAll(),  E_NOT_IMPLEMENTED ); 



    if(ok == 1) { 
     OUT_GREEN(); 
     printf("%s: ok", module_name); 
     OUT_WHITE(); 
    } 

输出,我得到如下:

Run tests 
storageSize: 1 
set: 1 
clear: 0 
invert: 1 
invert: 1 
fail line 84 (which is second invert) 

我试图找到哪里是错误的,但我什么也看不到。也许你们和女孩们可以看到?

+0

什么是所有'PETER_xxx'的东西?这与测试计划中的调用有什么关系? – Barmar

+0

@Barmar你可以离开它。这就是我的模块名称 – gawron103

+1

在处理位操作时,通常应该使用'unsigned int'。 – Barmar

回答

0

所有的位操作函数都错误地寻址所需的位,并在工作结束时破坏存储的值。他们采取这种形式:

uint8_t temp = *(storages[id])/BITS_IN_BYTE; 

    // ... perform some operation on temp ... 

    *(storages[id]) = temp; 

现在观察到,即使temp的价值的所有操作都省略了,最终的结果会在大多数情况下,是一个改变存储的值。

我想参数bit被认为是uint8_t序列storages[i]表示的位数组的索引。然后,你可以写

uint8_t temp = (storages[id])[bit/BITS_IN_BYTE]; 

    // ... perform some operation on temp ... 

    (storages[id])[bit/BITS_IN_BYTE] = temp; 

注意如何,在这种情况下,表达指定用于初始化temp的对象是一样的表达指定在其中记录temp的终值的对象。

+0

也许你是对的,但不幸的是它不是为我工作 – gawron103

+1

。 @ gawron103我建立并测试了你的代码,John Bollinger的修补程序适用于我,它对我来说没有意义,为什么你要在存储上取得价值s [i]并除以8.在这个测试的情况下,它是2,所以temp变为0,然后你或者在第4位并保存为16,那么当你再次拔出时,你除以16/8,temp为2 ,那么你再次在第4位,现在是18了。不是你想要的。 – cleblanc

+0

嗯,好吧,但你只是改变了功能机构? – gawron103