保证C中(void*)数组的精确数据宽度

保证C中(void*)数组的精确数据宽度,c,arrays,types,C,Arrays,Types,我在C中有一个简单的函数,它提供了指向数据数组的void*指针。我知道这个内存块中每个单独数据点的大小(以字节为单位),并且需要保证我可以修改这个块中的每个数据点,而不会意外地改变相邻的数据点。在本例中,我想将每个值递减1 所有数据点为8位、16位或32位 例如: void myFunction(void*数据、大小数组化、大小宽度perdatapoint) { 如果(!数据) 返回-1; 尺寸w=每个数据点的宽度; int numPoints=数组化/widthPerDataPoint; in

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

所有数据点为8位、16位或32位

例如:

void myFunction(void*数据、大小数组化、大小宽度perdatapoint)
{
如果(!数据)
返回-1;
尺寸w=每个数据点的宽度;
int numPoints=数组化/widthPerDataPoint;
int i;

对于(i=0;i代码似乎并不完全不合理。我个人可能会这样做:

 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;
}
开关(widthPerDataPoint)
{
案例1:
{
int8_t*dptr=数据;
对于(i=0;i

这里的优点是,您不会在每个循环中都得到一系列条件。编译器可能会以任何方式对其进行排序,但我并不总是相信编译器能够解决这些问题,而且我认为这也有点干净。

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

 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;
}
开关(widthPerDataPoint)
{
案例1:
{
int8_t*dptr=数据;
对于(i=0;i

这里的优点是,您不会在每个循环中都得到一系列条件。编译器可能会以任何方式对其进行排序,但我并不总是相信编译器能够解决这些问题,而且我认为这也有点干净。

根据定义,将
t*
类型的指针增加n将使其移动
n*sizeof(t)
字节。因此,编译器可以保证一致性。不用担心。

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

int8\u t
保证正好是8位,如果
CHAR\u BIT==1
,正好是1字节

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

typedef nameintN\u t指定有符号整数类型 宽度为N,无填充位,2的补码 因此,int8\t表示这样的有符号整数类型 宽度正好为8位

尽管出于您的目的,使用
uint8\u t
uint16\u t
等可能更有意义

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

#include <stdint.h>
#ifdef UINT8_MAX
/* uint8_t exists */
#else
/* uint8_t doesn't exist */
#endif
#包括
#ifdef UINT8U最大值
/*uint8\t存在*/
#否则
/*uint8\t不存在*/
#恩迪夫
(如果
CHAR\u BIT!=8
,则不会定义
int8\u t
uint8\u t
。)

这是标准仅保证最小尺寸的
[u]intleast\u t
[u]intfast\u t
类型


您必须保证数组和其中的偏移量都正确对齐,以适合您访问它所使用的类型。我想您已经在处理了。

int8\t
保证正好是8位,如果
CHAR\u BIT==1
,正好是1字节

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

typedef nameintN\u t指定有符号整数类型 宽度为N,无填充位,2的补码 因此,int8\t表示这样的有符号整数类型 宽度正好为8位

尽管出于您的目的,使用
uint8\u t
uint16\u t
等可能更有意义

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

#include <stdint.h>
#ifdef UINT8_MAX
/* uint8_t exists */
#else
/* uint8_t doesn't exist */
#endif
#包括
#ifdef UINT8U最大值
/*uint8\t存在*/
#否则
/*uint8\t不存在*/
#恩迪夫
(如果
CHAR\u BIT!=8
,则不会定义
int8\u t
uint8\u t
。)

这是标准仅保证最小尺寸的
[u]intleast\u t
[u]intfast\u t
类型


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

下面如何

  • 将值复制到任意大小的本地int

  • 对局部变量执行递减

  • 使用适当的位掩码将阵列中的位置归零 (例如,8位为~0xFF)

  • '和'将局部变量返回到数组中


  • 下面呢

  • 将值复制到任意大小的本地int

  • 对局部变量执行递减

  • 使用适当的位掩码将数据归零