1

我在 C 中有一个简单的函数,它提供了一个void*指向数据数组的指针。我知道这个内存块中每个单独数据点的大小(以字节为单位),并且需要保证我可以修改这个块中的每个数据点,而不会意外改变相邻的数据点。在此示例中,我想将每个值减 1。

所有数据点都是 8 位、16 位或 32 位。

例如:

void myFunction(void* data, size_t arraySize, size_t widthPerDataPoint)
{
  if(!data)
    return -1;
  size_t w = widthPerDataPoint;
  int numPoints = arraySize / widthPerDataPoint;
  int i;
  for(i=0; i<numPoints; i++)
  {
    if(w==1)       // 8 bit
      (*((int8_t*)data + i))--;
    else if(w==2)  // 16 bit
      (*((int16_t*)data + i))--;
    else if(w==4)  // 32 bit
      (*((int32_t*)data + i))--;
  }
}

不幸的是,根据 C99 规范,int8_t 等数据类型仅保证其最小大小,而不是确切大小。有什么方法可以就地重新转换和修改数据并保证我不会破坏我的阵列或接触相邻的数据点?此外,是否有一种等效的技术可以以某种方式适用于其他数据宽度(即:24 位、60 位等)?

4

4 回答 4

2

根据定义,将类型指针递增n会将其移位T*字节。因此,编译器向您保证一致性。不用担心。n * sizeof(T)

于 2013-01-26T00:50:12.177 回答
2

int8_t保证正好是 8 位,如果CHAR_BIT==1,正好是 1 字节。

引用最新 C 标准的N1570草案,第 7.20.1.1 节:

typedef 名称int N _t指定宽度为N的有符号整数类型,没有填充位,并且是二进制补码表示。因此,int8_t表示这种宽度正好为 8 位的有符号整数类型。

uint8_t尽管出于您的目的,使用,uint16_t等可能更有意义。

如果实现不支持具有所需特性的类型,则不会定义它们;您可以通过检查来检测这一点,例如:

#include <stdint.h>
#ifdef UINT8_MAX
/* uint8_t exists */
#else
/* uint8_t doesn't exist */
#endif

(如果CHAR_BIT != 8,那么既不int8_tuint8_t不会被定义。)

它是标准只保证最小尺寸的[u]intleast_N_t[u]intfast_t类型。

您必须保证数组和其中的偏移量都针对您用来访问它的类型正确对齐。我想你已经在处理这个问题了。

于 2013-01-26T00:50:16.557 回答
1

该代码似乎并非完全不合理。我个人可能会做这样的事情:

 switch(widthPerDataPoint)
 {
    case 1:
       {
          int8_t *dptr = data;
          for(i = 0; i < numPoints; i++)
             dptr[i]--;
       }
       break;
    case 2:
       {
          int16_t *dptr = data;
          for(i = 0; i < numPoints; i++)
             dptr[i]--;
       }
       break;

    case 4:
       {
          int32_t *dptr = data;
          for(i = 0; i < numPoints; i++)
             dptr[i]--;
       }
       break;

    default:
       fprintf(stderr, "Someone gave the wrong width - width=%d\n", 
               widthPerDatapoint);
       break;
}

这里的好处是你不会在每个循环中得到一堆条件。无论如何,编译器可能会对其进行排序,但我并不总是相信编译器会解决这些问题——而且我认为它也更简洁一些。

于 2013-01-26T00:50:04.313 回答
-1

下面的呢?

  1. 将值复制到任何大小的本地 int

  2. 对局部变量执行减量

  3. 使用适当的位掩码将数组中的位置清零(例如,~0xFF 表示 8 位)

  4. '和' 将局部变量放回数组中。

于 2013-01-26T00:53:10.470 回答