指针,数组和函数

时间:2016-11-13 01:57:31

标签: c arrays function pointers

我编写了一个可以旋转4 x 4阵列的功能,现在我想输出它...但是我得到一堆警告,但它编译并且有效,所以我想我只做了一些"次要/正式"错误。

#include <stdio.h>

//-----------------------------------------------------------------------------
///
/// This function prints four 4x4 matrix
///
/// @param m1, m2, m3, m4 input matrix you want to print.
///
/// @return 0
//-----------------------------------------------------------------------------

void *print_matrix(char m1[4][4], char m2[4][4], char m3[4][4], char m4[4][4])
    {
        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < 4; j++)
            {
                printf("%c ", m1[i][j]);
            }
            printf(" ");
            for(int j = 0; j < 4; j++)
            {
                printf("%c ", m2[i][j]);
            }
            printf(" ");
            for(int j = 0; j < 4; j++)
            {
                printf("%c ", m3[i][j]);
            }
            printf(" ");
            for(int j = 0; j < 4; j++)
            {
                printf("%c ", m4[i][j]);
            }
            printf("\n");
        }
        printf("\n");
        return 0;
    }

//-----------------------------------------------------------------------------
///
/// This function rotates a 4x4 matrix 
/// (and collects tears from overworked students @2am, because wtf is  )
///
/// @param m, the matrix you want to rotate
///
/// @return m_r the rotated matrix
//-----------------------------------------------------------------------------

char *rotate_matrix(char m[4][4])
{
    static char m_r[4][4];
    for(int i = 0; i < 4; i++)
    {
        for(int j = 0; j < 4; j++)
        {
            m_r[i][j] = m[3-j][i];
        }
    }
    return *m_r;
}

int main(void)
{
char matrix_t [4][4] = {{ '-', '-', '-', '-' },
                        { '-', 'O', '-', '-' },
                        { 'O', 'O', 'O', '-' },
                        { '-', '-', '-', '-' }
                       };
char matrix_z [4][4] = {{   '-', '-', '-', '-' },
                        { '-', 'O', 'O', '-' },
                        { 'O', 'O', '-', '-' },
                        { '-', '-', '-', '-' }
                       };
char matrix_l [4][4] = {{   '-', '-', '-', '-' },
                        { '-', 'O', '-', '-' },
                        { '-', 'O', '-', '-' },
                        { '-', 'O', 'O', '-' }
                       };
char matrix_i [4][4] = {{   '-', '-', 'O', '-' },
                        { '-', '-', 'O', '-' },
                        { '-', '-', 'O', '-' },
                        { '-', '-', 'O', '-' }
                       };
char (*array)[4][4];

  print_matrix(matrix_t, matrix_z, matrix_l, matrix_i);
  array = rotate_matrix(matrix_t);
  print_matrix(array, matrix_z, matrix_l, matrix_i);
    return 0;
}

这是我得到的错误:

102:9: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]


array = rotate_matrix(matrix_t);

103:16: warning: passing argument 1 of ‘print_matrix’ from incompatible pointer type [-Wincompatible-pointer-types]


print_matrix(array, matrix_z, matrix_l, matrix_i);

note: expected ‘char (*)[4]’ but argument is of type ‘char (*)[4][4]’


void *print_matrix(char m1[4][4], char m2[4][4], char m3[4][4], char m4[4][4])

说实话,我没有得到这些错误,因为代码似乎有效,我从未超出界限,显然我没有做任何内存违规...... < / p>

1 个答案:

答案 0 :(得分:1)

警告是因为:

char *            // pointer to char         or to first element of char[]
char (*)[4]       // pointer to char[4]      or to first element of char[][4]
char (*)[4][4]    // pointer to char[4][4]   or to first element of char[][4][4]

是不同的类型。指针不仅仅表示内存位置,而且(通过其类型)应该如何解释内存位置。

一个棘手的问题是数组名称(或任何其他评估为数组的表达式)衰减指针。例如,这是完全有效的:

char abc[4] = "abc";    // abc is an array of four characters
char a = *abc;          // a is 'a', the first character of abc

。 。 。相反,你可以在指针上使用数组表示法(执行指针运算并立即取消引用结果):

char * abc = "abc";     // abc is a pointer (into static memory)
char c = abc[2];        // c is 'c', the third character of abc

因此char *char ()[]可互换,char (*)[4]可与char ()[][4]互换,char (*)[4][4]可与char ()[][4][4]互换。

使额外棘手的原因是C并不完全支持将数组作为函数参数传递(尽管如果你真的想要它,你可以通过包装它来实现相同的效果结构中的数组并传递它)。它确实允许您将函数参数声明为具有数组类型,但这实际上是具有指针类型的函数参数的语法糖。所以这三个签名是等价的:

void *print_matrix(char m1[4][4], char m2[4][4], char m3[4][4], char m4[4][4])
void *print_matrix(char m1[][4], char m2[][4], char m3[][4], char m4[][4])
void *print_matrix(char (*m1)[4], char (*m2)[4], char (*m3)[4], char (*m4)[4])

您的代码有效,因为您的各种警告都会被取消:

  • rotate_matrix 应该返回char (*)[4](指向char[][4]的第一行的指针)或char (*)[4][4](指向一个完整的char[4][4])。相反,你让它返回char *,为了实现这一点,你取消引用所需的指针,从而获得(在数组到指针衰减之后)指向矩阵第一行的第一个元素的指针。当然,所有这些指针都指向相同的内存位置,只是使用不同的类型。
    • 要使用返回类型char (*)[4]声明它,您可以编写char (*rotate_matrix(char m[4][4]))[4]。 。 。但最好是声明row类型typedef char row[4],然后再写row * rotate_matrix(char m[4][4])。在这种情况下,您将在结尾返回m_r,它会衰减到指向m_r第一行的指针。
    • 使用返回类型char (*)[4][4]声明它,同样的事情,只需要额外的[4]&#(和matrix而不是row这样的名称) 。在这种情况下,您最后会返回&m_r,这意味着指向整个m_r的指针。
    • 上述方法中的任何一种都可以,恕我直言,但您当然必须调整呼叫网站以进行匹配。对于本答复的其余部分,我将假设我们正在执行第二个版本,即返回类型为char (*)[4][4]的版本。
  • array的类型为char (*)[4][4],很好。 array = rotate_matrix(matrix_t)中的代码警告是由于rotate_matrix的错误声明。但是返回指针的实际值已经很好了,至少在典型的平台上是这样。
    • 也就是说,如果您要将此类型用于array,那么您应该将其称为array_ptr,因为它是指针你通常的阵列类型。
  • 但是你将array作为参数传递给print_matrix,它带有char [4][4]类型的参数,意思是char (*)[4]。您无法将char (*)[4][4](指向4行4个字符的数组的指针)转换为char (*)[4](指向4个字符数组的指针)。要解决此问题,您只需要通过传递array取消引用*array

(注意:我不确定所有上述隐式转换实际上都是保证可以工作;指向不同类型对象的指针可能并非在所有平台上都是可互换的。甚至在典型的现代平台上,它们 都是可互换的,你可能会遇到严格的别名规则,这意味着你的编译器可能最终会执行完全破坏你的代码的优化。但它通常 工作。)