簡體   English   中英

為什么GCC會編譯此錯誤代碼?

[英]Why GCC compiles this erroneous code?

我試圖編譯類似:

struct A
{   int a;
    struct B
    {    int c;
    };
};

現在,當我編譯這段代碼時,編譯器會向我顯示一條警告消息:

declaration does not declare anything [enabled by default]

我知道我還沒有定義struct B任何實例。 那將意味着我將無法訪問變量c 仍然編譯器會編譯此代碼並顯示警告。 重點是什么? 為什么編譯器不給出編譯錯誤呢?

添加的信息:
struct A的大小等於我機器上int的大小!

因為您可以這樣做:

struct A
{   int a;
    struct B
    {    int c;
    };
};

int main()
{
    struct A a = {1};
    struct B b = {2};

    return a.a + b.c;
}

注意:

  • 在聲明B ,您需要使用分號(缺少代碼)
  • 這不是特別有用 ,但是我想它可能有一定的記錄目的(例如,建議類型之間的關系或分組)
  • 在C ++中,第二個變量的類型為A::B ,但是C的作用域規則不同(實際上所有結構都屬於全局結構名稱空間)

至於允許它的動機...

struct Outer {
    struct {
        int b;
    } anon;
    /* this ^ anonymous struct can only be declared inside Outer,
       because there's no type name to declare anon with */

    struct Inner {
        int c;
    } named;
    /* this ^ struct could be declared outside, but why force it to be
       different than the anonymous one? */

    struct Related {
        double d;
    };
    /* oh no we have no member declared immediately ... should we force this
       declaration to be outside Outer now? */

    struct Inner * (*function_pointer)(struct Related *);
    /* no member but we are using it, now can it come back inside? */

    struct Related excuse;
    /* how about now? */
};

一旦允許這樣的嵌套類型聲明,我懷疑是否有任何特殊動機要求立即有該類型的成員。

這樣做是合法的(但風格極其糟糕):

struct A {   
    int a;
    struct B {    
        int c;
    };
};
struct B B_instance;
struct A A_instance;

而且編譯器不知道使用結構類型的更高版本的變量,因此它實際上不應出錯。

通常,警告表示該代碼可能未達到您的預期目的,但在該語言中是合法的。 編譯器說:“這可能不是您真正想做的,但是我必須允許您這樣做,因為該語言表明它是允許的。”編譯器無法為您提供此代碼的錯誤,因為C標准允許這樣做,因此必須予以允許(除非您明確要求此類錯誤,例如使用GCC的-Werror選項將警告變為錯誤)。

C標准不會嘗試定義程序中有意義的所有內容。 例如,這些在C語言中是合法的:

3;
if (x) then foo(); else foo();
x = 4*0;

第一條語句沒有副作用,並且不使用其返回值。 但這在C語言中是合法的,因為語句可能只是一個表達。 第二條語句僅調用foo() ,因此if是毫無意義的。 在第三條語句中,乘以四是沒有意義的。

編寫一個禁止所有無意義的C標准非常困難。 這當然不值得付出努力。 因此,這就是您的答案的一部分:當編寫C標准的委員會構建該語言時,他們是否想花費大量時間重寫技術規范以排除不合理的內容? 有時是的,如果避免某些可能導致嚴重錯誤的事情似乎很有價值。 但是在很多時候,這是不值得的,並且會使規范變得不必要。

但是,編譯器可以識別其中的某些內容並警告您。 這有助於捕獲許多印刷錯誤或其他錯誤。

另一方面,有時這些構造是由異常情況引起的。 例如,一個程序可能具有預處理器語句,這些語句在為不同的目標或不同的功能構建時以不同的方式定義struct A 在某些目標中,可能是struct A不需要struct B成員,因此未聲明它,但是struct B的聲明(類型,不是對象)仍然存在,只是因為它更易於編寫預處理器語句就是這樣。

因此,編譯器需要允許這些事情,以避免干擾編寫各種程序的程序員。

實際上,您在這里聲明了struct B ,但您沒有在聲明該類型的變量。

這是一個警告,但您應解決此警告。 也許您的意思是:

struct A
{   int a;
    struct B
    {
        int c;
    } c;
};

暫無
暫無

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

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