无法将整数数组作为参数传递给局部参数为字符指针的函数

Unable to pass integer array as argument to function whose local argument is character pointer

我有一个 main 函数声明了一个整数数组。我想将此数组传递给参数类型为 char * 的函数。我无法更改被调用函数的签名。

我的目标是将 main 的整数数组 data1 的内容复制到 disp 的整数数组 data2 中,但是当我尝试以下代码时,我得到了不正确的值。 data2[0]= 10,data2[1]= 0,data2[2]= 0,data2[3]= 0,data2[4]= 20.

如何更正它以产生 data2[0]= 10,data2[1]= 20,data2[2]= 30,data2[3]= 40,data2[4]= 50 ?

注意: data2data1 的大小不一定相同。它可以是相同的大小或更大。我希望 data2 的前五个元素最终与 data1 的相应元素相同。

#include<stdio.h>

void disp(char *buffer)
{
    int itr, data2[5];
    for(itr=0;itr<5;itr++)
    {
        data2[itr]=(int*)buffer[itr];
        printf("data2[%d]= %d\n",itr,data2[itr]);
    }
}

int main(void)
{
    int data1[5]={10,20,30,40,50};
    disp((char*)data1);
    return 0;
}

例如在函数中使用这个语句

data2[itr] = *(int*)( buffer + itr * sizeof( int  ) );

否则,由于 buffer 的类型为 char *,因此通常表达式 buffer[itr] 不会指向正确对齐的 int 类型的对象。

或者如 @n. 'pronouns' m 在评论中指出的那样,您可以使用此语句

data2[itr] = ((int*)buffer )[itr];

其实是一样的

那就是你需要正确应用指针算法。

如您所知,您正在向函数发送 int 数组,您可以安全地将其转换为 int *

void disp(char *buffer)
{
    int *intBuffer = (int *) buffer;
    int itr, data2[5];

    for ( itr=0; itr < 5; itr++)
    {
        data2[itr] = intBuffer[itr];

        printf("data2[%d]= %d\n", itr, data2[itr]);
    }
}

函数调用似乎不是问题所在。您可以将 data1 强制转换为 char *,因为这是匹配函数参数类型所必需的。这实际上是一种特殊情况,因为它甚至可以通过结果 char *.

访问 pointed-to 数据。

问题出在 disp() 中读回数据。本声明:

        data2[itr]=(int*)buffer[itr];

已损坏,因为索引运算符 [] 的优先级高于强制转换运算符。结果,您正在读取 buffer 指向的数据的 itrth 字节,将其转换为类型 int *,将结果转换为隐含到 int(如果编译器尚未发出警告,请调高编译器的警告级别)并将最终结果存储在 data2 中。可能通过类型 int * 作为中间形式实际上是 no-op.

您可以进行的最简单的更改是插入括号以覆盖默认的运算符优先级:

        data2[itr] = ((int*)buffer)[itr];

首先将 buffer 转换回 int *,然后访问 itrth int指向哪个,就是你想要的。

然而,就我个人而言,如果我依赖于参数实际上是一个 int * 但无法正式更新参数类型(但无论如何可以修改函数实现)那么我会创建一个 correctly-typed 复制作为我做的第一件事:

void disp(char *buffer) {
    int *int_buffer = (int *) buffer;

那我以后就可以了

    // ...

        data2[itr] = int_buffer[itr];

    // ...

并且通常在处理业务时就好像我已经能够适当地设置参数类型一样。

或者,对于此特定用途,您可以选择简单地执行批量复制:

    memcpy(data2, buffer, 5 * sizeof(*data2));

完成,除了打印结果。

在您的代码中 data1int[5],五个 int 的数组。您可以将指向它的指针声明为 int (*)[5].

查看此代码,从您的 disp() 代码更改而来

void _disp(char* buffer)
{
    int(*original)[5] = (int(*)[5])(buffer);
    int data2[50];

    for (int itr = 0; itr < 5; itr += 1)
    {
        data2[itr] = (*original)[itr];
        printf("data2[%d]= %d\n", itr, data2[itr]);
    };
};

显示

Using (*)[5]

data2[0]= 10
data2[1]= 20
data2[2]= 30
data2[3]= 40
data2[4]= 50

对于此代码

#include <stdio.h>
void _disp(char*);

int main(void)
{
    int data1[5] = { 10,20,30,40,50 };
    printf("\nUsing (*)[5]\n\n");
    _disp((char*)data1);
    return 0;
}

void _disp(char* buffer)
{
    int(*original)[5] = (int(*)[5])(buffer);
    int data2[50];

    for (int itr = 0; itr < 5; itr += 1)
    {
        data2[itr] = (*original)[itr];
        printf("data2[%d]= %d\n", itr, data2[itr]);
    };
};

[在 MSVC 19.27 下编译]

一种可以说更简洁、更灵活的方式

此代码也有效

void _disp2(char* buffer)
{
    int*    pInt = (int*)buffer;
    int     data2[50];

    for (int itr = 0; itr < 5; itr += 1)
    {
        data2[itr] = *(pInt + itr);
        printf("data2[%d]= %d\n", itr, data2[itr]);
    };
};

这里我们只是将buffer转换为(int*),然后使用算术复制值,因为它会在内存中一个接一个地出现。

简答。使用联合和指针,而不是类型转换。

void disp(char *buffer)
{
int itr, data2[5];
for(itr=0;itr<5;itr++)
{
    data2[itr]=(int*)buffer[itr];
    printf("data2[%d]= %d\n",itr,data2[itr]);
}
}
/* Becomes */
void disp(char *buffer)
{
 union tag1 {
    char * cptr;
    int * iptr;
 } u;
int * itrp = NULL;  /* or null or even nil depending
                              on compiler headers...*/
int itr, data2[5];
u.cptr = buffer; /*in as char*   */
itrp = u.iptr;    /*out as int*  */

 for(itr=0;itr<5;itr++)
 {
    data2[itr]= itrp++;
    printf("data2[%d]= %d\n",itr,data2[itr]);
 }
}