ANSI C: назначение массивов и указателей на массивы - PullRequest
2 голосов
/ 09 декабря 2008

Ниже приведена упрощенная версия того, что я пытаюсь сделать, потому что я уверен, что вы не хотите разбираться с полным набором структур и прототипов функций для системы частиц.

float const materials[24][4][4] = {{{...}}};
typedef struct EmitterStruct  { float *material[4][4]; } Emitter;
typedef struct ParticleStruct { float material[4][4]; } Particle;
Emitter *myEmitter;

Emitter * createEmitter(float *material[4][4])
{
    Emitter * newEmitter;
    newEmitter = (Emitter *)malloc(sizeof(Emitter));
    newEmitter->material = materal; /* Returns "incompatable types in assignment" */
    return newEmitter;              /* I also tried newEmitter->material = &material */
}

int main(char *argv, int argc)
{
    myEmitter = createEmitter(materials[0]);
}

По сути, как показывает комментарий, я получаю ошибку компиляции. Я пробовал это несколькими разными способами, даже используя «float material [4] [4]» в структуре Emitter и подпись createEmitter. Однако потом, когда я пытаюсь скопировать значения в частицу для модификаций, используя:

for (i=0; i++; i<4)
{
    for (j=0; j++; j<4)
    {
        particle->material[i][j] = emitter->material[i][j];
    }
}

Я получаю другое несоответствие типов при копировании, даже если все объявлено как тип float [4] [4]. По сути, я хочу получить массив 4x4 из массива массивов 4x4, сохранить это в структуре эмиттера, а затем скопировать его в структуру частиц. Но я хочу скопировать значения только один раз.

Ответы [ 4 ]

3 голосов
/ 09 декабря 2008

Я отвечаю на ваш обновленный вопрос (который появился в вашем собственном ответе). Сначала ваш код:

float const materials[24][4][4] = {{{...}}};
typedef struct EmitterStruct  { float *material; } Emitter; /*Use just a plain pointer*/
typedef struct ParticleStruct { float material[4][4]; } Particle;
Emitter *myEmitter;

Emitter * createEmitter(float *material) /*Use a plain pointer here*/
{
    Emitter * newEmitter;
    newEmitter = (Emitter *)malloc(sizeof(Emitter));
    newEmitter->material = material; 
    return newEmitter;               
}

int main(char *argv, int argc)
{
    myEmitter = createEmitter(materials[0]);/*This decays into a pointer*/
}

НЕТ! Это не правильный путь. Распадается на указатель - да, но не указатель на число с плавающей точкой! Если вы передадите материалы [0], вы получите float const[4][4], который затухает до float const(*)[4] (указатель на его первый элемент), и этот указатель - то, что передается. Таким образом, вы хотите изменить это на это:

float const materials[24][4][4] = {{{...}}};
/*Use just a plain pointer to an array */
typedef struct EmitterStruct  { float const (*material)[4]; } Emitter; 
typedef struct ParticleStruct { float material[4][4]; } Particle;
Emitter *myEmitter;

/*Use a plain pointer here. Bet keep it float const, not only float!*/
Emitter * createEmitter(float const (*material)[4])
{
    Emitter * newEmitter;
    newEmitter = (Emitter *)malloc(sizeof(Emitter));
    newEmitter->material = material; 
    return newEmitter;               
}

int main(int argc, char ** argv) /* you swapped args here */
{
    myEmitter = createEmitter(materials[0]); /* This decays into a pointer */
}

Прочтите об этом здесь: на что указывает `int * userMask [3] [4]`? . Прочтите здесь о том, как правильно передавать массивы: Строки C ++: [] против *. Я бы порекомендовал вам хорошего помощника по С или С ++:)

1 голос
/ 09 декабря 2008

Что касается первого фрагмента, вы получаете эту ошибку, потому что массивы в C не могут быть назначены. Вы должны выполнить memcpy для копирования массивов.

Что касается второго фрагмента, у вас есть проблема со следующей строкой:

particle->material[i][j] = emitter->material[i][j];

Член material в Emitter представляет собой двумерный массив типа float*. Элемент material в Particle имеет тип float. Обратите внимание, что один является указателем, а другой - нет, поэтому они не могут быть назначены.

Вы можете написать следующее:

particle->material[i][j] = *(emitter->material[i][j]);

Но это при условии, что вы указали эти указатели на точку на что-то. Кроме того, вы можете изменить material в Emitter, чтобы он не был указателем. Я не могу сказать вам, что вы должны делать наверняка, потому что мне трудно расшифровать, какие именно ваши намерения основаны на коде, который вы дали.

0 голосов
/ 09 декабря 2008

Раньше я был экспертом в этом. К сожалению, я был вне этого слишком долго. Итак, вот фрагмент рабочего кода, который я написал около 6 лет назад. Я думаю, что это может указать вам правильное направление.

// get a color histogram of an image
int ***colorHistogram(PIXEL *inputImage, HEADER *imageHeader)
{
    int x, y, z;

    // a color histogram
    int ***histo;

    // allocate space for the histogram
    histo = (int ***)malloc(256 * sizeof(int**));
    for(x=0; x<256; x++)
    {
        histo[x]=(int **)malloc(256 * sizeof(int*));
        for(y=0; y<256; y++)
        {
            histo[x][y]=(int *)malloc(256 * sizeof(int));

            // initialize the histogram
            for(z=0; z<256; z++)
                histo[x][y][z] = 0;
        }
    }

    // fill the histogram
    for (x = 0; x < imageHeader->width * imageHeader->height; x++)
    {
        histo[((int) inputImage[x].r)][((int) inputImage[x].g)][((int) inputImage[x].b)]++;
    }

return histo;

}

В любом случае, я надеюсь, что это поможет.

0 голосов
/ 09 декабря 2008

Конечно, в секунду, когда я прошу помощи, я точно понимаю, что мне нужно было сделать.

float const materials[24][4][4] = {{{...}}};
typedef struct EmitterStruct  { float *material; } Emitter; /*Use just a plain pointer*/
typedef struct ParticleStruct { float material[4][4]; } Particle;
Emitter *myEmitter;

Emitter * createEmitter(float *material) /*Use a plain pointer here*/
{
    Emitter * newEmitter;
    newEmitter = (Emitter *)malloc(sizeof(Emitter));
    newEmitter->material = material; 
    return newEmitter;               
}

int main(char *argv, int argc)
{
    myEmitter = createEmitter(materials[0]);/*This decays into a pointer*/
}

А затем для копии:

for (i=0; i++; i<4)
{
    for (j=0; j++; j<4)
    {
        particle->material[i][j] = *(emitter->material[i * 4 + j];
    }
}

Doh ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...