Ваш камень преткновения больше относится к обработке структуры как параметра.Структура - это просто тип данных в C. Она передается как параметр, как и любой другой тип данных (int
, long
, char
и т. Д.), И следует тем же правилам.
Удобство typedef
позволяет вам указать параметр как Pyramid var
, вместо того, чтобы использовать полный struct Pyramid var
, как без него.На самом деле, вам даже не нужно имя _Pyramid
для структуры при использовании typedef
, например
typedef struct { /* you can simply typedef a struct */
double stone [N][N];
} pyramid_t;
Выше, typedef
просто псевдоним неназванной структуры, содержащей массив значений типа doubleна имя pyramid_t
, которое вы можете использовать при объявлении экземпляров структуры, например,
/* explicit way to initilize 2D array as 1st member of struct */
pyramid_t a = {{{10, 4, 2, 5, 1, 0, 0, 0},
{ 3, 9, 1, 2, 1, 0, 0, 0},
{-7, -5, 1, -2, -1, 0, 0, 0},
{-3, -5, 0, -1, 0, 0, 0, 0},
{-2, 1, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0}}};
Независимо от того, включаете вы _Pyramid
или нет, зависит от вас.(без этого вы просто теряете возможность ссылаться на struct _Pyramid
как на объявленный тип).
Ваша декларация int data[N*N];
- это «красная сельдь», отвлечение, которое не имеет никакого отношения кчто вы пытаетесь сделать.Вы инициализируете экземпляр вашей структуры в main()
.Вам просто нужно передать структуру (или, точнее, указатель на вашу структуру) в вашу функцию showme
[1] , чтобы значения там были доступны для печати.
ДляНапример, включая typedef
, чтобы указать, что вы передаете структуру в качестве параметра (где функция получает копию структуры), вы выводите значения, используя оператор dot
'.'
, как в вашей функции, например,
/* function type is void if it returns no value */
void showme (pyramid_t p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p.stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
Затем вы вызываете свою функцию в main()
как:
showme (a); /* passing a copy of the struct to showme() */
( note: функция получает копию структуры - так что попробуйтеизменив некоторые значения массива, а затем снова напечатайте содержимое обратно в main()
... все сделанные изменения будут потеряны)
Более эффективный способ передачи структуры - передача указателя на структуру,так что все, что передается, это адрес того, где структура хранится в памяти.Это не только предотвращает создание копии структуры, но и путем передачи адреса все изменения, которые вы вносите в значения структуры, затем сохраняются (потому что вы напрямую изменяете значения исходной структуры в памяти, а не просто вносите изменения вкопия).Когда вы передаете указатель на структуру (или в любое время, когда вы получаете доступ к значениям структуры через указатель), вы используете arrow operator
(->
) для доступа к членам структуры.Например, вы могли бы просто объявить showme()
, чтобы взять указатель на pyramid_t
вместо структуры, например,
/* function type is void if it returns no value */
void showme (pyramid_t *p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p->stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
Чтобы передать указатель на вашу структуру в main()
, выпросто используйте унарный оператор '&'
( адрес ), чтобы передать адрес a
, например,
showme (&a); /* pass pointer to prevent duplicating struct */
Теперь, если вы внесли изменения в значения массива в функции,изменения будут видны еще в main()
, потому что вы изменили значения, в которых они были сохранены в памяти, а не работали с копией, переданной функции.
Посмотрите на оба примера и поймите различия как в объявленииshowme()
функция и как она вызывается в main()
.Первый пример, передающий копию структуры и использующий оператор точки для доступа к члену:
#include <stdio.h>
#include <stdlib.h>
#define N 8 /* good job - if you need a constant, #define one (or more) */
typedef struct { /* you can simply typedef a struct */
double stone [N][N];
} pyramid_t;
/* function type is void if it returns no value */
void showme (pyramid_t p)
{
int i, j;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("%3g ", p.stone[i][j]);
putchar('\n'); /* use putchar() to output single char */
}
}
int main (void) { /* unless using argc, argv, use void */
/* explicit way to initilize 2D array as 1st member of struct */
pyramid_t a = {{{10, 4, 2, 5, 1, 0, 0, 0},
{ 3, 9, 1, 2, 1, 0, 0, 0},
{-7, -5, 1, -2, -1, 0, 0, 0},
{-3, -5, 0, -1, 0, 0, 0, 0},
{-2, 1, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0}}};
showme (a); /* passing a copy of the struct to showme() */
return 0; /* main() is type 'int' and returns a value */
}
Чтобы передать указатель, содержащий адрес исходной структуры, вы просто изменили бы объявлениеshowme()
и оператор, используемый для доступа к членам структуры:
/* function type is void if it returns no value */
void showme (pyramid_t *p)
{
...
printf("%3g ", p->stone[i][j]);
...
}
И, как объяснено выше, вы просто позвоните showme()
с адресом a
, например,
showme (&a); /* pass pointer to prevent duplicating struct */
В любом случае выходные данные будут одинаковыми, например,
Пример использования / Вывод
> bin\pyramid-struct.exe
10 4 2 5 1 0 0 0
3 9 1 2 1 0 0 0
-7 -5 1 -2 -1 0 0 0
-3 -5 0 -1 0 0 0 0
-2 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Посмотрите вещи и поймите различия, и позвольте мнезнать, если у вас есть дополнительные вопросы.
сноски:
[1] Хотя стиль С не является ошибкой, он обычно избегает использования переменных MixedCase
или camelCase
и использования имен в верхнем регистре (резервируя все имена в верхнем регистре для констант или макросов)., вместо того, чтобы использовать имена переменных всех строчных.Хотя это вопрос стиля и полностью зависит от вас, он может привести к неправильным первым впечатлениям при некоторых настройках.