недопонимание указателей массива, переданных функциям в C - PullRequest
1 голос
/ 09 февраля 2012

Почему операторы печати в функции не соответствуют отпечаткам верхнего уровня?

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

void bar(float **foo)
{
  printf(" &foo[0][0]    %f \n", &foo[0][0]);
}

int main()
{
  float mat[5][5], **ptr;
  mat[0][0] = 3.0f;
  ptr = (float **)mat;
  printf("  mat[0][0]    %f \n",  mat[0][0]);
  printf(" &ptr[0][0]    %f \n", &ptr[0][0]);
  bar(ptr);
}

результаты:

 mat[0][0]     3.000000 
 &ptr[0][0]    3.000000 
 &foo[0][0]    -0.005548 

Ответы [ 2 ]

1 голос
/ 09 февраля 2012

Несколько других получили вас за то, что похоже на путаницу между mat[0][0] типа float и &ptr[0][0] типа float *, но у вас есть еще одна более тонкая проблема: массивы не указатели.

Обычно массивы очень похожи на указатели, но по очень тонким причинам float [][] не совместим с float **, как float [] и float *.

Во многих контекстах (таких какпередаваемый в функцию), массив распадается на указатель на свой первый элемент .Таким образом, mat распадается до &mat[0].Тип массива T [] распадается на указатель T *, что означает, что тип mat распадается на (и тип &mat[0]) равен float (*)[], то есть указатель на массив фиксированразмер.

Вот разница между float * и float[]:

float *     float[]
+-----+     +-----+-----+
| ptr | --> | 0.0 | 1.0 |
+-----+     +-----+-----+

Теперь вот разница между float ** и float[][]:

float **    float *[]   float[][]         float (*)[]
+-----+     +-----+     +-----+-----+     +-----+     (imagine this
| ptr | --> | ptr | --> | 0.0 | 1.0 | <-- | ptr |     pointing to
+-----+     +-----+     +-----+-----+     +-----+     the 0.0 cell)
            | ptr | --> | 2.0 | 3.0 |
            +-----+     +-----+-----+

Эти типы, слева направо, указатель на указатель на float, массив указателей на float, массив массивов float s и указатель на массив из float s.Адрес &float[0], преобразованный в float **, получает разыменованную дважды как указатель , даже если есть только один указатель - указатель на float[0] (и, следовательно, остальная часть массива),Любое значение, которое вы получите через это, является мусором.

1 голос
/ 09 февраля 2012

Вы должны печатать указатели, используя %p. не %f. Кроме того, состав (float**)mat не имеет никакого смысла.

Когда вы говорите &((float**)mat)[0][0], вы фактически ищете указатель по адресу mat. если указатели шире, чем значения с плавающей точкой, вы будете читать из некоторых других байтов в стеке, и они могут изменяться при вызове функций.

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