使用空指针(C)连接两个数组

Kur*_*o95 5 c arrays function concatenation memcpy

我想将两个相同类型的数组连接成一个具有相同类型的新数组。但是问题是我必须使用void指针,从某种意义上说,我的代码从第三个元素开始将无法工作。我在互联网上搜索了一下,但似乎没人遇到这个问题

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void array_float_fill(float *arr1, float *arr2, int n, int m){
    for(int i = 0;i<n;i++){
        *(arr1+i)=i+n;
    }
    for(int i = 0;i<m;i++){
        *(arr2+i)=i+m;
    }
}

void array_concat(void *arr1, void *arr2, void *arr3, int n, int m,int size){
    for(int i=0;i<n;i++){
        memcpy((arr3+i),(arr1+i),size); 
    }   
    for(int i=0;i<m;i++){
        memcpy((arr3+i+n),(arr2+i),size);
    }
}

int main(int argc, char const *argv[])
{
    int n=10;
    int m=10;
    float f1[n];
    float f2[m];
    array_float_fill(f1,f2,n,m);
    printf("%f",*(f1+3));
    float* f3 = malloc((n+m) * sizeof(float));
    array_concat(f1,f2,f3,n,m,sizeof(float));
    printf("%f",*(f3+3));
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

我用for-loop 尝试了将每个元素复制到新数组,因为该函数只会给我一个指向数组开始的指针。邓诺(Dunno)为什么不起作用。任何帮助和提示将不胜感激

Seb*_*ach 4

void*指针算术...

...在标准 C 中实际上是不允许的。gcc 允许它并假设基本操作数大小为 1。因此它如下

指数假设

使用 时,您将字节与索引混淆了memcpy

当(非标准地)将整数添加到void指针时,整数的含义(在 gcc 中)是字节偏移量的含义。这与类型指针不同,编译器将为您进行适当的缩放:

void *p;
int i;
p[i];   // This will be literally p+i after compiling on your compiler
Run Code Online (Sandbox Code Playgroud)

但例如:

float *p;
int i;
p[i];   // This will be p+i*sizeof(float) after compiling.
Run Code Online (Sandbox Code Playgroud)

所以而不是...

for(int i=0;i<n;i++){
    memcpy((arr3+i),(arr1+i),size); 
}   
for(int i=0;i<m;i++){
    memcpy((arr3+i+n),(arr2+i),size);
}
Run Code Online (Sandbox Code Playgroud)

...你必须写(这仍然是特定于编译器的):

for(int i=0;i<n;i++){
    memcpy((arr3+i*size), (arr1+i*size), size);
}
for(int i=0;i<m;i++){
    memcpy((arr3+i*size+n*size), (arr2+i*size), size);
}
Run Code Online (Sandbox Code Playgroud)

...或遵循标准:

for(int i=0;i<n;i++){
    memcpy((char*)arr3+i*size, (char*)arr1+i*size, size);
}
for(int i=0;i<m;i++){
    memcpy((char*)arr3+i*size+n*size, (char*)arr2+i*size, size);
}
Run Code Online (Sandbox Code Playgroud)

通过转换为char*,您可以强制将基本操作数大小设置为 1 个字节(更准确地说,1 个 C 字节),考虑到 concat 函数的通用性质,这正是您想要的。

然而

请注意,您可以将任意步长传递给memcpy,但实际上并不需要循环;相反,只需执行以下操作:

memcpy((char*)arr3, arr1, size*n);
memcpy((char*)arr3+n*size, arr2, size*m);
Run Code Online (Sandbox Code Playgroud)

仅在进行算术运算时才需要转换。