как передать пользовательский тип массива фиксированной длины без предупреждения (C и OpenCL) - PullRequest
1 голос
/ 10 ноября 2011

У меня есть несколько причин для определения типа для массива фиксированной длины, например:

typedef float fixed_array_t[NX][NY];

Затем я хочу передать ссылки на fixed_array_t экземпляры другим функциям.Я получаю предупреждение компилятора как от GCC, так и от CLANG, хотя вижу правильное поведение.

Что говорит мне это предупреждение компилятора и как должен быть изменен мой код, чтобы избежать предупреждения?Бонус, почему я должен #define размер массива?Константы времени компиляции, очевидно, не работают.error: variably modified ‘fixed_array_t’ at file scope

Вот небольшой демонстрационный код:

#include <stdio.h>
#define NX 2  // also, why does const int NX = 2; not work?
#define NY 3
typedef float fixed_array_t[NX][NY];

void array_printer( const fixed_array_t arr )
{
    int i, j;
    for (i = 0; i < NX; i++ )
        for( j=0; j < NY; j++ )
            printf("Element [%d,%d]=%f\n", i,j, arr[i][j] );
}

int main( int argc, char ** argv )
{
    fixed_array_t testArray = { {1,2,3}, {4,5,6} };
    array_printer( testArray );
}

Предупреждение GCC:

warning: passing argument 1 of ‘array_printer’ from incompatible pointer type

Предупреждение CLANG (фактически компилируется эквивалентный код в OpenCL):

warning: incompatible pointer types passing 'fixed_array_t' (aka 'real [2][3]'), expected 'real const (*)[3]'

Тем не менее, программа работает нормально:

Element [0,0]=1.000000
Element [0,1]=2.000000
Element [0,2]=3.000000
Element [1,0]=4.000000
Element [1,1]=5.000000
Element [1,2]=6.000000

Ответы [ 3 ]

2 голосов
/ 10 ноября 2011

Я думаю, причина этой проблемы в том, что array_printer может передавать то, что считает const char (посредством ссылки через указатель), но вызывающий код имеет неконстантную ссылку и, следовательно, может изменять указанные значения.

Попробуйте изменить:

void array_printer( const fixed_array_t arr )

до

void array_printer( fixed_array_t arr )
2 голосов
/ 10 ноября 2011

Это просто неудачный угловой случай в C.

Тип формального параметра const fixed_array_t arr является синонимом const float (*arr)[XY], а фактический параметр totalArray оценивается как тип float (*)[XY].

A pointer to array XY of float просто не считается неявно конвертируемым в pointer to array XY of const float.Возможно, так и должно быть, но это не так.

0 голосов
/ 10 ноября 2011

Если вы просто хотите, чтобы проблема была решена, вы можете использовать struct для инкапсуляции вашего массива:

$ cat struct.c ; make CFLAGS=-Wall -Wextra struct ; ./struct
#include <stdio.h>

#define NX 2
#define NY 3

typedef struct fixed {
    float arr[NX][NY];
} fixed_t;

void array_printer( const fixed_t f)
{
    int i, j;
    for (i = 0; i < NX; i++ )
        for( j=0; j < NY; j++ )
            printf("Element [%d,%d]=%f\n", i,j, f.arr[i][j] );
}


int main(int argc, char *argv[]) {
    fixed_t f = {.arr={ {1,2,3}, {4,5,6} }};
    array_printer(f);
    return 0;
}

cc -Wall    struct.c   -o struct
Element [0,0]=1.000000
Element [0,1]=2.000000
Element [0,2]=3.000000
Element [1,0]=4.000000
Element [1,1]=5.000000
Element [1,2]=6.000000

Нет предупреждений, ошибок и только немного больше раздражает в использовании (скорее * f.arr[][])чем arr[][] в array_printer, например).

Если вы измените struct fixed, включив в него размеры NX и NY, вы можете даже иметь несколько объектов разного размера в вашемпрограмма.(Несмотря на то, что вы немного потеряете преимущества известных во время компиляции границ, я не уверен, сколько это действительно вас покупает.)

...