指针和typedef结构,在C

时间:2018-09-30 00:56:05

标签: c pointers struct typedef

我有一个程序必须使用ShowMe (int *p),并且在调用主函数时需要将其从typedef Pyramid A中拉出。 这是typedef结构声明

typedef struct _Pyramid
{
double element [N][N];
} Pyramid;

我遇到了不兼容的错误,我知道它们不是同一类型。我已经尝试过投放,但被告知无法这样做。 我已经尝试了我目前知道的所有方法来使它起作用。那么我该如何在主目录中调用function ShowMe (int *p)并将其传递给金字塔A的值呢? 如果需要,我将发布代码。但是我厌倦了被告知自己在做错什么(我大多数人已经从错误中弄清楚了),却没有任何正确方法的指导。我会再次强调。我是C的新手,我很累,在发布之前已经工作了几天以上。

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

#define N 8

typedef struct _Pyramid{
double stone [N][N];
} Pyramid;



int data[N*N];



Pyramid ShowMe(int *p)  // pass in data and return Pyramid
 {
      int i;
      int j; 
        for (i=0; i<N; i++)
        {
            for (j=0; j<N; j++)
            {
                printf("%g ", a.stone[i][j]);
            }//Inner for
            printf("\n");
        }//Outer For
 }//IZZ




int main(int argc, char **argv)
{
    // special case that allows us to initialize this way
    Pyramid 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(int *A);


}//main

2 个答案:

答案 0 :(得分:0)

将类型['a', ['e'], ['s', 'o'], []] 设置为Pyramid*将违反严格的别名规则,并可能导致某些未定义的行为。为ShowMe()传递int*而不是char*是一种可能的解决方法,因为char指针是严格别名规则的例外。有关更多信息和解决方法,请检查this post

答案 1 :(得分:0)

您的绊脚石更多是关于将结构作为参数进行处理的。结构只是C中的一种数据类型。它像其他任何数据类型(intlongchar等)一样作为参数传递。规则。

typedef的便利性使您可以将参数指定为Pyramid var,而不必像不使用参数一样使用完整的struct Pyramid var。实际上,在使用_Pyramid时,甚至不需要typedef的名称,例如

typedef struct {    /* you can simply typedef a struct */
    double stone [N][N];
} pyramid_t;

上面,typedef只是为未命名的结构加上别名,该结构包含一个由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() */

注意:,该函数将接收该结构的副本-因此请尝试更改某些数组值,然后再次将内容打印回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] 尽管不是错误,但C样式通常避免使用MixedCasecamelCase变量以及所有大写名称(保留所有大写名称) (用于常量或宏),而不是使用所有小写字母的变量名称。尽管这是样式问题,完全取决于您,但这可能会导致某些设置中的第一印象错误。