使用“char”的布尔数组

时间:2010-08-07 22:39:03

标签: c arrays free malloc boolean

我创建了一个实际上代表一个存储在char中的8个布尔数组的对象。我用它来学习更多关于按位运算符以及在C中创建自己的对象的内容。所以我有两个问题:

  1. 我是否可以确定以下代码 总是有效吗?
  2. 这是一个很好的实现 制作一个不会迷路的物体 在C中,除非你发布它 自己。
  3. 守则:

    /*
     *  IEFBooleanArray.h
     *  IEFBooleanArray
     *
     *  Created by ief2 on 8/08/10.
     *  Copyright 2010 ief2. All rights reserved.
     *
     */
    
    #ifndef IEFBOOLEANARRAY_H
    #define IEFBOOLEANARRAY_H
    
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    typedef char * IEFBooleanArrayRef;
    
    void IEFBooleanArrayCreate(IEFBooleanArrayRef *ref);
    void IEFBooleanArrayRelease(IEFBooleanArrayRef ref);
    int IEFBooleanArraySetBitAtIndex(IEFBooleanArrayRef ref, 
                                     unsigned index, 
                                     int flag);
    int IEFBooleanArrayGetBitAtIndex(IEFBooleanArrayRef ref, 
                                     unsigned index);
    
    #endif
    

    /*
     *  IEFBooleanArray.c
     *  IEFBooleanArray
     *
     *  Created by ief2 on 8/08/10.
     *  Copyright 2010 ief2. All rights reserved.
     *
     */
    
    #include "IEFBooleanArray.h"
    
    void IEFBooleanArrayCreate(IEFBooleanArrayRef *ref) {
        IEFBooleanArrayRef newReference;
    
        newReference = malloc(sizeof(char));
        memset(newReference, 0, sizeof(char));
        *ref = newReference;
    }
    
    void IEFBooleanArrayRelease(IEFBooleanArrayRef ref) {
        free(ref);
    }
    
    int IEFBooleanArraySetBitAtIndex(IEFBooleanArrayRef ref, unsigned index, int flag) {
        int orignalStatus;
    
        if(index < 0 || index > 7)
            return -1;
    
        if(flag == 0)
            flag = 0;
        else
            flag = 1;
    
        orignalStatus = IEFBooleanArrayGetBitAtIndex(ref, index);
        if(orignalStatus == 0 && flag == 1)
            *ref = *ref + (int)pow(2, index);
        else if(orignalStatus == 1 && flag == 0)
            *ref = *ref - (int)pow(2, index);
    
        return 0;
    }
    
    int IEFBooleanArrayGetBitAtIndex(IEFBooleanArrayRef ref, unsigned index) {
        int result;
        int value;
    
        value = (int)pow(2, index);
        result = value & *ref;
    
        if(result == 0)
            return 0;
        else
            return 1;
    }
    

    我更像是一个Objective-C家伙,但我真的想更多地学习C语言。任何人都可以要求更多的“家庭作业”,我可以提高自己吗?

    谢谢你, ief2

5 个答案:

答案 0 :(得分:10)

  1. 不要使用< 0检查无符号类型,它没有意义,并在某些编译器上引发警告。
  2. 请勿使用未签名类型而未指定其大小(unsigned intunsigned char等)。
  3. 如果flag == 0为什么要将其设置为0
  4. 我不喜欢在*中抽象typedef,但不是错误
  5. 您无需致电memset()将单个字节设为0
  6. 使用pow来计算位偏移是疯狂的。查看<<>>运营商,然后使用这些运营商
  7. 完全填充您的if声明条件,或为将来调试痛苦做好准备。
  8. 如果您在&函数中使用按位运算符|+而不是算术-SetBitAtIndex,则不需要所有这些无论如何,复杂的if陈述。
  9. 您的GetBitAtIndex例程无法检查index
  10. 从这个列表中,#9是唯一一个意味着你的程序在所有情况下都无法工作的人,我想。我没有详尽地测试它 - 这只是第一眼检查。

答案 1 :(得分:4)


pow(2,index)是产生位掩码的低效方法之一。我可以想象使用Ackermann函数可能会更糟,但pow()几乎是缓慢的。您应该使用(1<<index)代替。此外,C'ish设置/清除值的方式看起来不同。以下是关于此问题的最新问题:


如果你想以高效和便携的方式在C中使用munge,那么你真的应该看看这个位错综复杂的页面,如果你提到“位”,那么每个人都会建议你“不知何故:


以下代码序列:

if(result == 0)
        return 0;
    else
        return 1;

可以写为return (result != 0);return resultreturn !!result(如果结果应强制为0或1)。虽然明确表达意图总是一个好主意,但大多数C程序员更喜欢“结果结果”。因为在C中这是使你的意图清晰的方式。如果看起来不确定,就像一个警告标签说“原始开发人员是一个Java人并且不了解位”或其他东西。


newReference = malloc(sizeof(char));
memset(newReference, 0, sizeof(char));

malloc + memset(x,0,z) == calloc();


您可以为IEFBooleanArraySetBitAtIndex报告错误(无效索引),但为IEFBooleanArrayGetBitAtIndex报告。这是不一致的。使错误报告统一,或者库的用户将进行错误检查。

答案 2 :(得分:3)

至于访问char对象中的位#n,而不是使用pow()函数,可以使用移位和屏蔽:

设置位#n:

a = a | (1 << n);

清除位#n:

a = a & (~(1 << n));

得到#n:

return ((a >> n) & 1);

答案 3 :(得分:1)

似乎没有人提到这一点(我很惊讶),但是......你不能告诉我你在认真做malloc(sizeof(char))?这是一个非常小的分配。将它作为堆分配对象没有意义。只需将其声明为char

如果您想要进行某种程度的封装,可以执行:typedef char IEFBoolArray;并使用访问器函数来操作IEFBoolArray。或者甚至做typedef struct { char value; } IEFBoolArray;但是考虑到数据的大小,在堆上一次分配这些数据将是非常疯狂的。让类型的消费者只是将其声明为内联并使用访问者。

此外......您确定要char吗?如果将其提升为更大的代码,例如int

,您可能会获得更好的代码

答案 4 :(得分:1)

除了Carl Norum积分:

  1. 除非必须(即存储大量位值),否则不要以这种方式在char中保存空间。由于必须执行按位操作等,因此速度要慢得多。
  2. 在大多数架构中,你通过mallocing char来浪费内存。在大多数现代架构中,一个指针比char更多4到8倍,另外你有关于malloced块的数据。
  3. 可能静态大小不是最好的方法,因为它不灵活。我认为使用speciall函数没有任何好处。
  4. 截至第3点类似:

    typedef struct {
        uint64_t size;
        uint64_t *array;
    }bitarray;
    
    bitarray bitarray_new(uint64_t size) {
        bitarray arr;
        arr.size = size;
        arr.array = calloc(size/8);
        return arr;
    }
    
    void bitarray_free(bitarray arr) {
        free(arr.array);
    }
    
    void bitarray_set(bitarray arr, uint64_t index, int bit) {
      assert (index <= arr.size)
      if (bit)
        array[index/8] |= 1 << (index % 8);
      else
        array[index/8] ^= ~(1 << (index % 8));
    }
    
    void bitarray_get(bitarray arr, uint64_t index, int bit) {
      assert (index <= arr.size)
      return array[index/8] & 1 << (index % 8);
    }
    
      

    Copyright 2010 ief2. All rights reserved.

    实际上他们不是。您volontarly published许可下cc-by-sa他们只保留一些权利。此外,您希望我们阅读和修改代码,因此保留所有权利毫无意义。

    (PS。我建议不要在限制性许可下发布琐碎的工作 - 它确实看起来很专业 - 除非你有法律问题这样做)

      

    这是一个很好的实现,可以创建一个不会在C中丢失的对象,除非你自己发布它。

    对不起?