使用“char”的布尔数组

发布于 2024-09-13 11:52:04 字数 2188 浏览 8 评论 0 原文

我创建了一个对象,它实际上表示存储在 char 中的 8 个布尔值的数组。我这样做是为了更多地了解按位运算符以及在 C 中创建自己的对象。所以我有两个问题:

  1. 我可以确定下面的代码是否 总是有效吗?
  2. 这是一个很好的实施吗 制作一个不会丢失的物品 在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

I made an object that actually represents an array of 8 booleans stored in a char. I made it to learn something more about bitwise operators and about creating your own objects in C. So I've got two questions:

  1. Can I be certain if the below code
    always works?
  2. Is this a good implementation to
    make an object that can't get lost
    in C, unless you release it
    yourself.

The Code:

/*
 *  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;
}

I'm more of an Objective-C guy, but I really want to learn C more. Can anyone request some more "homework" which I can improve myself with?

Thank you,
ief2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

蓝色星空 2024-09-20 11:52:07

至于访问 char 对象中的位 #n,您可以使用移位和屏蔽来代替使用 pow() 函数:

设置位 #n:

a = a | (1 << n);

清除位 #n:

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

获取位 #n:

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

As for accessing bit #n in your char object, instead of using pow() function, you can use shifting and masking:

Set bit #n:

a = a | (1 << n);

Clear bit #n:

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

Get bit #n:

return ((a >> n) & 1);
九公里浅绿 2024-09-20 11:52:07

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

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

此外...您确定要它是 char 吗?如果将其提升为更大的代码(例如 int),您可能会生成稍微更好的代码。

Nobody seems to be mentioning this (I am surprised), but... You can't tell me you're seriously doing malloc(sizeof(char))? That is a very small allocation. It doesn't make sense to make this a heap allocated object. Just declare it as char.

If you want to have some degree of encapsulation, you can do: typedef char IEFBoolArray; and make accessor functions to manipulate an IEFBoolArray. Or even do typedef struct { char value; } IEFBoolArray; But given the size of the data it would be sheer madness to allocate these one at a time on the heap. Have consumers of the type just declare it inline and use the accessors.

Further... Are you sure you want it to be char? You might get slightly better code generated if you promote that to something larger, like int.

寂寞笑我太脆弱 2024-09-20 11:52:07

除了 Carl Norum 的观点之外:

  1. 除非必须(即存储大量位值),否则不要以这种方式节省 char 空间。它要慢得多,因为您必须执行按位运算等。
  2. 在大多数体系结构上,您通过分配 char 来浪费内存。在大多数现代架构上,一个指针比 char 多花费 4 到 8 倍的时间,而且您还拥有有关 malloced 块的数据。
  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);
}

版权所有 2010 ief2。保留所有权利。

实际上并非如此。您自愿发布它们在cc-by-sa 许可,仅保留部分权利。此外,您希望我们阅读并修改代码,因此保留所有权利是没有意义的。

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

这是一个很好的实现,可以使对象在 C 中不会丢失,除非您自己释放它。

对不起?

In addition to Carl Norum points:

  1. Don't save space in char such way unless you have to (i.e. you store a lot of bit values). It is much slower as you have to perform bitwise operations etc.
  2. On most architectures you waste memory by mallocing char. One pointer takes 4 to 8 times more then char on most modern architectures and additionally you have data about the malloced chunk as it.
  3. Probably static size is not the best approach as it inflexible. I wouldn't see any benefit of using speciall functions for it.

As of 3rd point something like:

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.

Actually they are not. You volontarly published them under cc-by-sa licence and only some right are reserved. Additionally you want us to read and modify the code so reserving all right is pointless.

(PS. I would advice against publishing trivial work under restrictive licences anyway - it does not look professionaly - unless you have legal issues to do so)

Is this a good implementation to make an object that can't get lost in C, unless you release it yourself.

Sorry?

冬天旳寂寞 2024-09-20 11:52:06
  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 进行边界检查。

我认为,从该列表中,#9 是唯一一个意味着您的程序无法在所有情况下运行的选项。我没有对其进行详尽的测试——这只是初步检查。

  1. Don't check unsigned types with < 0, it's meaningless and causes warnings on some compilers.
  2. Don't use unsigned types without specifying their size (unsigned int, unsigned char, etc).
  3. If flag == 0 why are you setting it to 0?
  4. I don't like abstracting the * away in a typedef, but it's not wrong by any means.
  5. You don't need to call memset() to set a single byte to 0.
  6. Using pow to calculate a bit offset is crazy. Check out the << and >> operators and use those instead
  7. Fully parenthesize your if statement conditions or be prepared for debugging pain in your future.
  8. If you use the bitwise operators & and | instead of arithmetic + and - in your SetBitAtIndex function, you won't need all those complicated if statements anyway.
  9. Your GetBitAtIndex routine doesn't bounds check index.

From that list, #9 is the only one that means your program won't work in all cases, I think. I didn't exhaustively test it - that's just a first glance check.

可遇━不可求 2024-09-20 11:52:06

pow(2,index) 是生成位掩码的效率较低的方法之一。我可以想象使用 Ackermann 函数可能会更糟,但是 pow() 速度相当慢。您应该使用 (1< 代替。此外,设置/清除值中的位的 C'ish 方式看起来有所不同。这是最近的一个与此相关的问题:


如果你想以一种高效且可移植的方式在 C 中处理位,那么你真的应该看看 bit twiddling 页面,如果你提到的话,这里的每个人都会向你推荐“位”不知何故:


以下代码序列:

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

可以写成 return (result != 0);return resultreturn !!result (如果结果应强制为 0 或 1)。尽管明确意图总是一个好主意,但大多数 C 程序员更喜欢“结果结果”;因为在 C 语言中这是明确意图的方式。 if 看起来很可疑,就像一个警告贴纸,上面写着“原始开发人员是 Java 人员,对位了解不多”之类的。


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

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


您可以为 IEFBooleanArraySetBitAtIndex 报告错误(无效索引),但不能< /strong> 代表 IEFBooleanArrayGetBitAtIndex。这是不一致的。使错误报告统一,否则库的用户将搞砸错误检查。


pow(2,index) is among the more inefficient ways to produce a bit mask. I can imagine that using the Ackermann function could be worse, but pow() is pretty much on the slow side. You should use (1<<index) instead. Also, the C'ish way to set/clear a bit in a value looks different. Here's a recent question about this:


If you want to munge bits in C in an efficient and portable way, then you really should have a look at the bit twiddling page, that everyone here will suggest to you if you mention "bits" somehow:


The following code sequence:

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

can be written as return (result != 0);, return resultor return !!result (if result should be forced to 0 or 1) . Though it's always a good idea to make an intent clear, most C programmer will prefer 'result result;' because in C this the way to make your intent clear. The if looks iffy, like a warning sticker saying "Original developer is a Java guy and knows not much about bits" or something.


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

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


You have a way to report an error (invalid index) for IEFBooleanArraySetBitAtIndex but not for IEFBooleanArrayGetBitAtIndex. This is inconsistent. Make error reporting uniform, or the users of your library will botch error checking.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文