9

Say i have an array in C

int array[6] = {1,2,3,4,5,6}

how could I split this into

{1,2,3}

and

{4,5,6}

Would this be possible using memcpy?

Thank You,

nonono

123hal321
  • 2,080
  • 4
  • 24
  • 25
  • yes, but depending on what you need to do with the pieces, it might be unnecessary. what are you trying to do with the pieces? – Mat May 01 '11 at 17:19
  • run them through a function which operates on them. However, I cannot modify the function. – 123hal321 May 01 '11 at 17:20
  • memcpy will copy the content (bytewise) from the source buffer to the destination buffer. you're array will not actually be split in two. you have to create two new arrays and copy the content from the first to the new ones – Marius Bancila May 01 '11 at 17:21

4 Answers4

22

Sure. The straightforward solution is to allocate two new arrays using malloc and then using memcpy to copy the data into the two arrays.

int array[6] = {1,2,3,4,5,6}
int *firstHalf = malloc(3 * sizeof(int));
if (!firstHalf) {
  /* handle error */
}

int *secondHalf = malloc(3 * sizeof(int));
if (!secondHalf) {
  /* handle error */
}

memcpy(firstHalf, array, 3 * sizeof(int));
memcpy(secondHalf, array + 3, 3 * sizeof(int));

However, in case the original array exists long enough, you might not even need to do that. You could just 'split' the array into two new arrays by using pointers into the original array:

int array[6] = {1,2,3,4,5,6}
int *firstHalf = array;
int *secondHalf = array + 3;
Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
9
// create space for 6 ints and initialize the first 6
int array[6] = {1,2,3,4,5,6};
// reserve space for two lots of 3 contiguous integers
int one[3], two[3]; 
// copy memory of the first 3 ints of array to one
memcpy(one, array, 3 * sizeof(int)); 
// copy 3 ints worth of memory from the 4th item in array onwards
memcpy(two, &array[3], 3 * sizeof(int)); 
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
  • Thanks, but please can you annotate the lines of code, I don't understand what they do - especially `int one[3] = (int[3])array;`. Is this casting `array` to an array of length 3? – 123hal321 May 01 '11 at 17:24
  • +1 from me, I like how you show a solution which does a deep copy and which does not need `malloc`/`free`. Minor question from a non-native english speaker: did you mean to write `for two *s*lots` in your code comment? – Frerich Raabe May 02 '11 at 07:10
  • @Frerich Raabe: No I mean to use lots. See the second definition for English: http://en.wiktionary.org/wiki/lot, one can group things into "lots". Generally in C I would encourage absolutely minimal use of malloc. – Matt Joiner May 02 '11 at 08:54
1

You don't have to split them. If you have

int *b = array + 3;

you have the second array. When you pass an array to a function, it's turned into a pointer anyway.

pmg
  • 106,608
  • 13
  • 126
  • 198
lang2
  • 11,433
  • 18
  • 83
  • 133
0

See the magic how memcpy works, no need to exclusively split the arrays. The changes made in destination array are automatically go to source array and vise versa.

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

double *** double3d(long int dim1,long int dim2,long int dim3)
{
    long int i,j,k;
    double ***array;
    array=(double ***)malloc(dim1*sizeof(double **));
    for(i=0;i<dim1;i++)
    {
     array[i]=(double **)malloc(dim2*sizeof(double *));
     for(j=0;j<dim2;j++)
      array[i][j]=(double *)malloc(dim3*sizeof(double ));
    }
    return array;
}// end double3d

void summ(double ***A,double ***B, double ****C)
{
    int i ,j ,k;
    for(i=0;i<10;i++)
    for(j=0;j<5;j++)
    for(k=0;k<5;k++)
    (*C)[i][j][k]=A[i][j][k]+B[i][j][k];
}

void main()
{
   int i,j,k,nx,ny;
   double ***M1, ***M2, ***M3, ***M4,***M5,***M6;
   nx=5;ny=5;
    M1=double3d(10,nx,ny);
    M2=double3d(10,nx,ny);
    M3=double3d(10,nx,ny);
    M4=double3d(5,nx,ny);
    M5=double3d(5,nx,ny);
    M6=(double ***)malloc(10*sizeof(double **));

    for(i=0;i<10;i++)
    {
        for(j=0;j<nx;j++)
           for(k=0;k<ny;k++)
           {
           M1[i][j][k]=i;
           M2[i][j][k]=1;
           }
    }

// Note random values are in M4 and M5 as they are not initalised
    memcpy(M6,     M4, 5 * sizeof(double **));
    memcpy(M6+5,   M5, 5 * sizeof(double **));

    for(i=0;i<5;i++)
    {
       for(j=0;j<nx;j++)
          for(k=0;k<ny;k++)
          {
               M4[i][j][k]=200;
               M5[i][j][k]=700;
          }
    }

printf(" printing M6 Memcpy before addtion\n");
    for(j=0;j<nx;j++)
    {
       for(k=0;k<ny;k++)
           printf("%f ",M6[4][j][k]);
       printf("\n");
       for(k=0;k<ny;k++)
           printf("%f ",M6[9][j][k]);
       printf("\n");
    }
    // calling for non memcpy array
    summ(M1,M2,&M3); printf(" Non memcpy output last value : %f \n",M3[9][nx-1][ny-1]);
    // calling for memcpy
    summ(M1,M2,&M6); printf(" memcpy output last value : %f \n",M6[9][nx-1][ny-1]);
printf(" printing M6 Memcpy for two sets after addtion\n");
    for(j=0;j<nx;j++)
    {
       for(k=0;k<ny;k++)
           printf("%f ",M6[4][j][k]);
       printf("\n");
    }
    for(j=0;j<nx;j++)
    {
       for(k=0;k<ny;k++)
           printf("%f ",M6[9][j][k]);
       printf("\n");
    }

    free(M6);// cleared M6

printf(" printing M4 Memcpy after deleting M6\n");
    for(j=0;j<nx;j++)
    {
       for(k=0;k<ny;k++)
           printf("%.1f ,%.1f ,%.1f ,%.1f ,%.1f ",M4[0][j][k],M4[1][j][k],M4[2][j][k],M4[3][j][k],M4[4][j][k]);
       printf("\n");
    }

printf(" printing M5 Memcpy after deleting M6\n");
    for(j=0;j<nx;j++)
    {
       for(k=0;k<ny;k++)
           printf("%.1f ,%.1f ,%.1f ,%.1f ,%.1f ",M5[0][j][k],M5[1][j][k],M5[2][j][k],M5[3][j][k],M5[4][j][k]);
       printf("\n");
    }
 }