1

I have a 50 x 50 matrix arr[50][50] and need to swap the values in the sub-array arr[0] and arr[1]. ie, the whole 50 elements in each sub-array need to be swapped.

The only way I can think of to do this is by using a loop like:

for(i=0; i<50; ++i)
{
    int t = arr[0][i];
    arr[0][i] = arr[1][i];
    arr[1][i] = t;
}

I was wondering if there were any simpler or shorter methods? Using pointers maybe?

I tried things like

int *t = arr[0];
arr[0] = arr[1];
arr[1] = t;

but it gave error at the first line about "incompatible types when assigning to type 'int[2]' from type 'int *' ".

Then I tried pointer to an array

int (*t)[50] = arr[0];
arr[0] = arr[1];
arr[1] = t;

This time I got error at the second line about "incompatible types when assigning to type 'int[50]' from type 'int *' ".

J...S
  • 5,079
  • 1
  • 20
  • 35
  • Well a faster way would be to use xor expression instead of using a third variable - `arr[0][i] = arr[0][i]^arr[1][i]; arr[1][i] = arr[0][i]^arr[1][i]; arr[0][i] = arr[0][i]^arr[1][i];`, The complexity would be the same but the constant factors change. – GAURANG VYAS Jun 18 '17 at 05:06
  • 3
    The only way you can copy data with the `=` is from a simple variable, a single array element, or a `struct`. Consider using `int temp[50]` and `memcpy`. – Weather Vane Jun 18 '17 at 05:07
  • You will need to copy the rows (or swap them). You can use something like `int tmp[50];` then `memcpy (tmp, arr[0], 50 * sizeof *tmp); memcpy (arr[0], arr[1], 50 * sizeof *arr[0]); memcpy (arr[1], tmp, 50 * sizeof *arr[1]);` – David C. Rankin Jun 18 '17 at 05:08
  • 2
    @GAURANG VYAS: Quite the oppoosite. The *faster* way would be not to obfuscate the code and help the compiler to figure out that you just want to swap two values. Your XOR trick is a notorious anti-pattern that has to be avoided. – AnT stands with Russia Jun 18 '17 at 05:09
  • @AnT can you explain more ? – GAURANG VYAS Jun 18 '17 at 05:12
  • 1
    @GAURANGVYAS the OP's swap loop does 3 reads and 3 writes in each iteration (apart from `i`) but your way does 6 reads and 3 writes. – Weather Vane Jun 18 '17 at 05:16
  • 2
    @GAURANG VYAS: A simple swap with a third variable will be immediately recognized by a decent compiler as a swap operation. The compiler will be able to implement it in the most efficient way: maybe a single XCHNG instruction, maybe even your XOR trick, maybe something else. Compilers are better at such micro-optimizations. Meanwhile, your XOR trick might just confuse the compiler and impede these optimizations. – AnT stands with Russia Jun 18 '17 at 05:16
  • Regarding the swap trick: https://stackoverflow.com/questions/36906/what-is-the-fastest-way-to-swap-values-in-c – anatolyg Jun 18 '17 at 07:29

3 Answers3

5

If your matrix is implemented as arr[50][50] then the only way to physically swap two rows is to physically exchange data in memory. Your cycle is one way to do it. The rest would be just variations of that approach. You can swap matrix elements one-by-one (your cycle), you can swap the entire rows using an intermediate row-sized buffer (memcpy approach). All of them still do the same thing. There's no way around it.

If your array were implemented differently - say, a "jagged" array implemented as array of pointers to sub-arrays, then you would be able to just swap two pointers and be done with it. But in case of arr[50][50] it is not possible.

If you wish, you can just "convert" your current array into a "jagged" version by a separate row-pointer array. That row-pointer array will now become your matrix a, while the original a[50][50] will become a_data

int a_data[50][50];

int *a[50];
for (unsigned i = 0; i < 50; ++i)
  a[i] = a_data[i];

/* Fill the matrix */
for (unsigned i = 0; i < 50; ++i)
  for (unsigned j = 0; j < 50; ++j)
    a[i][j] = rand();

/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
  for (unsigned j = 0; j < 50; ++j)
    printf("%d ", a[i][j]);
  printf("\n");
}

/* Swap the rows */
int *temp = a[0];
a[0] = a[1];
a[1] = temp;

/* Print the matrix */
for (unsigned i = 0; i < 50; ++i)
{
  for (unsigned j = 0; j < 50; ++j)
    printf("%d ", a[i][j]);
  printf("\n");
}

Note, that despite the physical structure of a is now different, you can still use a[i][j] syntax to work with it.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

As explained in the comments, and within the other answers, in order to swap rows of an actual 2D array (as apposed to an array of pointers), you must copy/move the data from the source to target row in memory. The most straight forward way to approach this is either with a loop to copy element-by-element to temporary storage to effect the swap, or use the memory copy functions provided by the C-library (e.g. memcpy or memmove). A simple implementation using memcopy (shown with a 3x10 array for array for purposes of the example) would be:

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

enum { ROW = 3, COL = 10 };

void swaprow (int (*a)[COL], int c1, int c2);
void prna (int (*a)[COL]);

int main (void) {

    int a[ROW][COL] = {{0}};

    for (int i = 0; i < ROW; i++)
        for (int j = 0; j < COL; j++)
            a[i][j] = i;

    prna (a);
    swaprow (a, 0, 1);
    putchar ('\n');
    prna (a);

    return 0;
}

void swaprow (int (*a)[COL], int c1, int c2)
{
    int tmp[COL];

    memcpy (tmp, a[c1], COL * sizeof *tmp);
    memcpy (a[c1], a[c2], COL * sizeof *a[c1]);
    memcpy (a[c2], tmp, COL * sizeof *a[c2]);
}

void prna (int (*a)[COL])
{
    for (int i = 0; i < ROW; i++) {
        for (int j = 0; j < COL; j++)
            printf ("%2d", a[i][j]);
        putchar ('\n');
    }

}

Example Use/Output

$ ./bin/array2d_swap_row
 0 0 0 0 0 0 0 0 0 0
 1 1 1 1 1 1 1 1 1 1
 2 2 2 2 2 2 2 2 2 2

 1 1 1 1 1 1 1 1 1 1
 0 0 0 0 0 0 0 0 0 0
 2 2 2 2 2 2 2 2 2 2

Look things over and let me know if you have any questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

You will have to copy the data to be swapped with memcpy, I have provided sample to program to show how you can do it(ie swap arr[0] and arr[1]).

int main(void) {
    // your code goes here
    int t[3];
    int arr[3][3]={{1,2,3},{4,5,6},{7,8,9}};
    printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
    printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
    memcpy(t,arr[0],sizeof(t));
    memcpy(arr[0],arr[1],sizeof(t));
    memcpy(arr[1],t,sizeof(t));
    printf("\n%d %d %d",arr[0][0],arr[0][1],arr[0][2]);
    printf("\n%d %d %d",arr[1][0],arr[1][1],arr[1][2]);
    return 0;
}
Pras
  • 4,047
  • 10
  • 20