簡體   English   中英

指針和typedef結構,在C中調用函數時該怎么做

[英]Pointers and typedef structs, what to do when you call a function in C

我有一個必須使用ShowMe (int *p)的程序,調用它時需要從main函數中將值從typedef Pyramid A中拉出。這是typedef結構聲明

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

我遇到了不兼容的錯誤,我知道它們不是同一類型。 我已經嘗試過投放,但被告知無法這樣做。 我已經嘗試了我目前知道的所有方法來使它起作用。 那么我該如何在main中調用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

Pyramid*類型轉換為int*將違反嚴格的別名規則,並可能導致某些未定義的行為。 為ShowMe()傳遞char*而不是int*是一種可能的解決方法,因為char指針是嚴格的別名規則的例外。 有關更多信息和解決方法,請查看此文章

您的絆腳石更多是關於將結構作為參數進行處理的。 struct只是C中的一種數據類型。它像其他任何數據類型( intlongchar等)一樣作為參數傳遞,並遵循相同的規則。

typedef的便利性使您可以將參數指定為Pyramid var而不必像不使用它一樣使用完整的struct Pyramid var 實際上,當使用typedef ,甚至不需要_Pyramid作為結構名稱,例如

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()初始化struct的實例。 您只需要將結構(或更好的是,指向結構的指針)傳遞給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變量,而避免使用全大寫的名稱(為常量或宏保留所有大寫的名稱),而不是使用所有小寫的變量名稱。 雖然這是樣式問題,完全由您決定,但在某些情況下可能導致錯誤的第一印象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM