2015-11-15 5 views
1

я получаю два типа ошибок:Я получаю «несовместимый тип указателя», и я не понимаю, почему

жалобы составителя

pr.c: В функции «главный»:

pr.c: 20: 2: предупреждение: проходя аргумент 1 из 'printMatrix' от несовместимого типа указателя [по умолчанию включено]

pr.c: 9: 6: Примечание: ожидаемый «константный Int (*) [80] ', но аргумент тип 'INT (*) [80]

pr.c: 22: 2: предупреждение: проходя аргумент 1 из 'огней' от несовместимого типа указателя [по умолчанию включено]

pr.c: 10: 6: примечание: ожидаемый 'const int (*) [80]', но аргумент имеет тип 'int (*) [80]'

Кажется, компилятор жалуется на получение неконстантной функции, которая принимает const, но мне сказали, что это правильный способ использования const ...

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

#define MAXCOL 80 
#define MAXROW 20 
#define randNormalize() srand(time(0)) 

void fillMatrix(int m[][MAXCOL], size_t rows, size_t cols); 
void printMatrix(const int m[][MAXCOL], size_t rows, size_t cols); 
void lights(const int m[][MAXCOL], size_t rows, size_t cols); 
int star(const int m[][MAXCOL], int row, int col); 

int main() 
{ 
    int m[MAXROW][MAXCOL]; 

    randNormalize(); 

    fillMatrix(m, 5, 5); 
    printMatrix(m, 5, 5); 

    lights(m, 5, 5); 

    return 0; 
} 

void fillMatrix(int m[][MAXCOL], size_t rows, size_t cols) 
{ 
    int i, j; 

    for(i = 0; i < rows; i++) 
     for(j = 0; j < cols; j++) 
      m[i][j] = rand()%21; 

} 

void printMatrix(const int m[][MAXCOL], size_t rows, size_t cols) 
{ 
    int i, j; 

    for(i = 0; i < rows; i++) 
    { 
     printf("\n"); 

     for(j = 0; j < cols; j++) 
      printf("%d ", m[i][j]); 
    } 

    printf("\n"); 
} 


void lights(const int m[][MAXCOL], size_t rows, size_t cols) 
{ 
    int i, j; 

    for(i = 1; i < rows - 1; i++) 
    { 
     printf("\n"); 

     for(j = 1; j < cols - 1; j++) 
     { 
      if(star(m, i, j)) 
       printf("*"); 
      else 
       printf(" "); 
     } 
    } 

    printf("\n"); 
} 



int star(const int m[][MAXCOL], int row, int col) 
{ 
    int i, j; 
    int sum = 0; 

    for(i = row - 1; i <= row + 1; i++) 
     for(j = col - 1 ; j <= col + 1; j++) 
      sum += m[i][j]; 

    return (sum/9 > 10); 
} 

Я ищу лучшее решение, которое не использует указатели, поскольку это было связано с упражнением курса, в котором мы еще не рассмотрели их (хотя я их изучил).

+0

'const'-thing отлично, но' fillMatrix' ожидает указатель на массив из 80 'int', в то время как вы передаете указатель на массив из 5. Это несовместимы. [Этот вопрос] (http://stackoverflow.com/questions/25790789/whats-the-difference-between-int-a5-and-inta5) может объяснить больше. – Kninnug

+0

Почему вещь const прекрасно? Я хочу избавиться от него: ~ (. – YoTengoUnLCD

+0

FYI, сообщения не являются двумя отдельными предупреждениями. Они являются частью одного и того же предупреждения. – kaylum

ответ

1

Проблема

При использовании m в вызове функции, как вы делаете, он распадается на указатель. Тип указателя, который m распадается, равен int (*)[5] - указатель на «массив из 5 int s».

Учитывая декларацию fillMatrix, ожидаемый тип аргумента int (*)[MAXCOL], т.е. int (*)[80] - указатель на «массив из 80 ints».

Эти два типа несовместимы.

Причина, по которой эти два типа несовместимы, можно понять, посмотрев, как компилятор ожидает, что указатели будут вести себя, и ожидаемый макет памяти.

Для объяснения я собираюсь изменить размеры массива 2 и 4.

Для

int m1[2][2]; 

макет памяти выглядит так:

m1[0][0] m1[1][1] 
|   | 
+---+---+---+---+ 
| | | | | 
+---+---+---+---+ 

Если вы объявляете указатель этого массива,

int (*p1)[2] = m1; 

Раскладка памяти с точки зрения указателя выглядит следующим образом:

p1  p1+1 p1+2 
|  |  | 
v  v  v 
+---+---+---+---+ 
| | | | | 
+---+---+---+---+ 

Теперь давайте создадим массив с размером 4 x 4 и рассмотрим, как распределение памяти выглядит с точки указателя зрения.макет

int m2[4][4]; 

Память:

m2[0][0]             m2[3][3] 
|               | 
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 
| | | | | | | | | | | | | | | | | 
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 

Указатель:

int (*p2)[4] = m1; 

Раскладка памяти с точки зрения указателя выглядит следующим образом:

p2    p2+1   p2+2   p2+3   p2+3 
|    |    |    |    | 
v    v    v    v    v 
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 
| | | | | | | | | | | | | | | | | 
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ 

Если сравнить, как указатель арифметика используется для е два различных типа указателя, вы увидите, что:

p1[1][0] совершенно иная p2[1][0] с точки зрения того, как значения этих указателей зачитываются перед выполнением указателя ->int разыменования.

Если p1 рассматривается как тот же тип, что и тип p2, то арифметика указателей очень легко приведет к доступу к массиву за пределы и приведет к неопределенному поведению.

Вот почему компилятор не будет использовать указатель типа int (*)[4], если ожидаемый тип аргумента - int (*)[80].

Решение

Есть много способов решить эту проблему. Самым простым решением является использование

int m[2][MAXCOL]; 
+0

Спасибо за все объяснение! Мне нужно немного понять все. – YoTengoUnLCD

+0

Примечание: этот ответ относится к ревизии 1 вопроса; он не учитывает несовместимость 'const'. – Armali

2

К сожалению, в C нет неявного преобразования из int[X][Y] в const int[X][Y]. Также не подразумевается переход от int (*)[Y] к const int (*)[Y].

Это недостаток в языке; нет никакой технической причины, почему такое преобразование не должно быть разрешено. (C++ разрешает это преобразование).

У вас есть два варианта, как непривлекательно:

  1. Пусть функции принимают int вместо const int
  2. Написать слепок при вызове const int функции, например, printMatrix((const int (*)[MAXCOL])m, 5, 5);

Обычно вариант 1 будет использоваться, и мы просто должны обойтись без сопзЬ корректности для многомерных массивов.

+0

Что касается варианта 2, то приведение должно иметь тип параметра, i. е. 'printMatrix ((const int (*) [MAXCOL]) m, 5, 5)'. – Armali

+0

@Armali fixed, ty –

Смежные вопросы