我创建了一个实际上代表一个存储在char中的8个布尔数组的对象。我用它来学习更多关于按位运算符以及在C中创建自己的对象的内容。所以我有两个问题:
守则:
/*
* 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
答案 0 :(得分:10)
< 0
检查无符号类型,它没有意义,并在某些编译器上引发警告。unsigned int
,unsigned char
等)。flag == 0
为什么要将其设置为0
?*
中抽象typedef
,但不是错误。memset()
将单个字节设为0
。pow
来计算位偏移是疯狂的。查看<<
和>>
运营商,然后使用这些运营商if
声明条件,或为将来调试痛苦做好准备。&
函数中使用按位运算符|
和+
而不是算术-
和SetBitAtIndex
,则不需要所有这些无论如何,复杂的if
陈述。GetBitAtIndex
例程无法检查index
。从这个列表中,#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 result
或return !!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积分:
截至第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中丢失的对象,除非你自己发布它。
对不起?