【问题标题】:C array: setting element at offsetC数组:在偏移处设置元素
【发布时间】:2016-11-13 21:06:24
【问题描述】:

我有一个二维数组声明为

static bool array[ROW][COL];

对于一个特定的函数,我想使用字节偏移量来设置一些元素,而不是使用索引,因为这个数组中的布尔值几乎可以保证每个都是 1 个字节。

loff_t *offset = 0;

所以我尝试以下行。

array + *offset = false;

但是,它编译时会出现警告“需要左值作为赋值的左操作数”。这个实现有什么问题,如何根据字节偏移设置数组的元素?

【问题讨论】:

  • 旁注:是什么让你如此确定“这个数组中的布尔值几乎保证每个都是 1 个字节”?顺便说一句,它们要么是 1 个字节,要么不是;在这种情况下,“几乎有保证”似乎有点不切实际。
  • 除非底层架构有位寄存器,否则bool (几乎)总是int 的大小。
  • 这一行:loff_t *offset = 0;loff_t *offset = NULL; 相同 C 语言不允许添加两个指针 建议:int offset = 0; array + offset = false;,第二个语句与:array[0][offset] = false; 相同

标签: c arrays offset


【解决方案1】:

您可以手动计算特定偏移量的索引,而不是直接通过乱用指针来指定字节偏移量,同时试图避免未定义的行为:

array[offset / COL][offset % COL] = ...

上述方法仅在sizeof (bool) == sizeof (char) 时有效。

如果你的程序已经做了这样的假设,你应该添加以下内容:

static_assert(sizeof (bool) == sizeof (char), "sizeof bool != sizeof char");

如果不是,您应该使用不同的(基于指针的)方法。

【讨论】:

  • 这是个好主意。你可以通过COL划分和修改来获得两个索引?
  • 这取决于 OP 需要什么。如果任务专门调用 fo byte offset,那么不会。这种方法是:1. 对原始意图的主要混淆,2. 根本不是字节偏移访问。这种方法执行布尔偏移访问,而不是字节偏移访问。
  • 我想知道什么编译器能够将它编译为一个简单的加法,如果offset(或COL)具有无符号类型,这将是等效的。
【解决方案2】:

您可以在二维数组中使用偏移量,就好像它是一维数组一样,但它并不完全正确,因为您的索引超出了子数组边界:

*(array[0] + *offset) = false;         // not strictly correct

对于这种语法,offset 必须包含许多 bool 类型,计算如下:

*offset = &array[row][col] - array[0];

或等效:*offset = &array[row][col] - &array[0][0];

另一种方法是使用字符类型的别名,但bool 可能大于char,所以这也是不正确的:

*((char*)array + *offset) = false;  // potentially incorrect

为了处理bool大于char的情况,我们可以使用:

*(bool *)((char*)array + *offset) = false;  // quite ugly

offset 应该这样计算:

*offset = (char*)&array[row][col] - (char*)array;

【讨论】:

  • @2501:是的,未定义的行为。 *((char*)array[0] + *offset) = false; 会被定义和正确吗?
  • 不,因为 bool 可能不是单个字节。严格阅读标准,它也可能超出范围。
  • 虽然它会起作用,但在转换为 char * 之前为什么要执行 array[0] 并不完全清楚。完全没有必要这样做[0]
  • @AnT:确实不需要[0],但我确实喜欢在应用强制转换时保持相同级别的间接性:array[0] 衰减为bool *。跨度>
  • @chqrlie:相同级别的间接?但是array 本身会衰减为bool (*)[COL]。这也是相同级别的间接(即只有一个级别)。 C 中的显式数组类型不会引入额外的间接级别。
【解决方案3】:

设置存储在数组array 中字节偏移量*offsetbool 值如下所示

*(bool *) ((char *) array + *offset) = true;

当然,您必须承担这种访问所带来的所有风险,因为这样的技术很容易违反严格的别名规则。一个更安全的选择可能是

bool new_value = true;
memcpy((char *) array + *offset, &new_value, sizeof new_value);

【讨论】:

    猜你喜欢
    • 2016-12-20
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多