簡體   English   中英

函數內部的函數聲明——為什么?

[英]Function declaration inside of function — why?

我正在閱讀“用 C 編程”一書,在第 10 章中找到了這樣的例子:

#include <stdio.h>

void test (int  *int_pointer)
{
     *int_pointer = 100;
}

int main (void)
{
     void test (int  *int_pointer);
     int  i = 50, *p = &i;

     printf ("Before the call to test i = %i\n", i);

     test (p);
     printf ("After the call to test i = %i\n", i);

     return 0;
}

我理解這個例子,但我不理解行void test (int *int_pointer); main里面。 為什么我要重新定義test的簽名? 這是慣用的C嗎?

void test (int *int_pointer); 只是函數test的聲明(或原型)。 無需此聲明main是因為你之前已經有函數定義main

如果test的定義在main之后,那么在調用它之前將其聲明放在那里是值得的,以便讓編譯器知道test的返回類型、參數數量和參數類型。

它絕對不是慣用的 C,盡管它是完全有效的(多重聲明是可以的,多重定義不是)。 這是不必要的,所以沒有它代碼仍然可以完美運行。

如果有的話,也許作者打算這樣做

void test (int *int_pointer);

int main (void) {

    ...

}

如果函數定義放在main ()

它不是慣用的 C,但仍然有效。

該行是函數test的聲明,而不是定義。 一個函數不能被多次定義,但有多個聲明是有效的。

它是完全慣用的 C,並且它實際上具有(有限的)實際用途——盡管這個例子沒有證明這一點。

當您在通常的全局級別聲明一個函數或其他名稱時,它會被帶入聲明之后代碼中的所有函數體的范圍內。 聲明一旦被引入就不能從作用域中移除。 該功能對翻譯單元的其余部分永久可見。

當您在花括號塊中聲明函數或其他名稱時,聲明的范圍僅限於該塊。 在另一個函數的范圍內聲明一個函數將限制其可見性,並且不會污染全局命名空間或使其對同一翻譯單元中定義的任何其他函數可見。

這在示例的情況下是沒有意義的,因為test的定義也將其引入了所有后續主體的范圍 - 但如果test是在另一個翻譯單元中定義的,或者即使它僅在此 TU 的最底部定義,將聲明隱藏在main中將保護之后定義的任何其他函數無法在其作用域中看到其名稱。

實際上,這用途有限——通常,如果您不希望某個函數可見,則將其放在另一個翻譯單元中(最好將其設為static )——但您可能會設計出一種您可能想要使用的情況這種構建不導出其組件的原始聲明的模塊加載系統的能力,或類似的東西(並且這不依賴於static /單獨的目標文件的事實可能與嵌入式/非- 托管目標環境,其中鏈接步驟可能不像在 PC 上那樣工作,允許您在純粹基於#include的構建系統中實現命名空間保護的措施)。

例子:

struct module {
    void * (* alloc)(size_t);
    void (* dealloc)(void *);
} loaded_module;

int main(void) {
    if (USE_GC) {   // dynamically choose the allocator system
        void * private_malloc_gc(size_t);
        void private_free_noop(void *);
        loaded_module = (struct module){ private_malloc_gc, private_free_noop };
    } else {
        void * private_malloc(size_t);
        void private_free(void *);
        loaded_module = (struct module){ private_malloc, private_free };
    }
    do_stuff();
    //...
}

// cannot accidentally bypass the module and manually use the wrong dealloc
void do_stuff(void) {
    int * nums = module.alloc(sizeof(int) * 32)
    //...
    module.dealloc(nums);
}

#include "allocator_implementations.c"

這不是慣用語; 您通常會在無法按順序獲取頭文件的代碼中看到它。

任何函數要么只在一個文件中使用,要么在多個文件中使用。 如果只在自己的文件中使用,應該是靜態的。 如果在多個文件中使用,它的聲明應該在一個頭文件中,任何使用它的人都應該包含頭文件。

你在這里看到的是非常糟糕的風格(函數應該是靜態的,或者聲明應該取自標題風格),而且也很沒有意義,因為編譯器已經可以看到聲明了。 由於函數在同一個文件中,所以並不危險; 如果聲明和函數不匹配,編譯器會告訴你。 當函數在不同的文件中時,我經常看到這種情況; 很危險。 如果有人更改了該功能,則程序很可能會崩潰或行為異常。

暫無
暫無

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

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