开发者

swapping array rows and printing, c

this is something that's been bugging me for the past two hours. I'm trying to swap two rows in a two dimensional array. This is not a problem, but I want to do it with a swap function that gets pointers. Here's what I have so far:

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

void swapRows(int **a, char **b)
{
    int *temp = *a;
    *a = *b; // WARNING #1
    *b = temp; // WARNING #1

}

void print(int a[][2],int rows,int cols)
{
    int i,j;
    for (i=0; i<rows; i++)
    {
        for (j=0; j<rows; j++)
        {
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
}

int main(void)
{
    int matrix[2][2] = {{1,2},{3,4}};
    print(matrix,2,2);
    swapRows(&matrix[0],&matrix[1]); //WARNING #2
    print(matrix,2,2);
    return EXIT_SUCCESS;
}

So, here are my questions:

1)The swap functions only swaps between the first elements in each array, which makes sense. How do I get it to swap the other elem开发者_开发百科ents? Do I HAVE to iterate the entire row?

2)When declaring print it only worked if i set a[][]2. Before that I tried writing int **arr but I had a segmentation fault. Why is that? Also, why must I specify the number of cols in the array argument? I have rows and cols for that, why does the compiler forces me to do so?

3)finally, using this version of print() I get a warning from the compiler passing argument 2 of ‘swapRows’ from incompatible pointer type (warning #2 in the code) and I get another warning (#1) : assignment from incompatible pointer type in swapRows(). Why is that? Thanks in advance!


The source of your confusion:

The type of

int m1[2][2]; // a *single* block of memory of size 2*2*sizeof(int)
              //
              // this is a *real* 2d-array

is not the same as that of

int **m2;  // a pointer of size sizeof(int*) almost certainly the 
           // equal to sizeof(void*)
           //
           // This could be made to point at at least two logically 
           // distinct blocks of memory and *act* like a 2d-array

Yes, m2 (pointer to a pointer) can be dereferenced using [][], but m1 (a actual two dimensional array) can not be dereferenced with **.

This means that your call to swap rows is a horrible error. Look why...

  • matrix[0] is the first sub array (and int[2] containing {1,2}), taking the address of it is a null operation that gets the address of matrix[0][0], which is a spot in memory containing the integer representation of 1 (that is this is a pointer-to-int).
  • A similar argument applies to &matrix[1] it points a memory containing 2.

The you call swapRows which thinks that these arguments are pointers-to-pointers-to-int (which they are not, so your compiler throws a warning). It will run though because a pointer-to-int is the same size as a pointer-to-pointer-to-int (that isn't strictly guaranteed, but you'll usually get away with it). What it does when it runs is swap the point-to-int sized contents of a with the pointer-to-int sized contents of b. If it happens to be the case that sizeof(int) == sizeof(int*) (which is not uncommon), this will amount to swapping matix[0][0] with matrix[1][0].

That is not what you wanted.

What can you do about it?

  • Declare matrix as a pointer to pointer and allocate the memory as in a ragged array, then use your existing swap
  • Declare matrix as an array of pointers and allocate memory for the rows, then use your existing swap
  • Keep the existing declaration of matrix and re-write the swap to swap every value.
  • Keep the existing declaration of matrix, but also provide an accessor array of pointers, use your existing swap on the accessor, and always use the accessor (the only possible advantage of this over the first two options is that everything resides on the stack).
  • Use the row-as-a-structure hack.

Row-as-a-structure

Consider this

typedef struct {
   int r[2];
} row_t;
row_t m3[2];

m3 is an array of structures each of which is an array of ints. Access is a little awkword: m3[i].r[j], but you can do

row_t temp = m3[n];
m3[n] = m3[m];
m3[m] = temp;

to swap rows.


Arrays and pointers are different things, although C makes them behave similarly in many cases. You also accidentally used a char instead of an int for the second parameter. Your swapRows function should be declared like this:

void swapRows(int (*a)[2], int (*b)[2])

You will need to swap (*a)[0] with (*b)[0] and (*a)[1] with (*b)[1].

C is converting the array into a pointer (with a warning), but that is confusing in this case.

It is just a limitation of C that arrays must have a size that is known at compile time.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜