2015-07-04 151 views
24

我有一個結構如下:不平凡的指定初始化不支持

struct app_data 
{ 
    int port; 
    int ib_port; 
    unsigned size; 
    int tx_depth; 
    int sockfd; 
    char *servername; 
    struct ib_connection local_connection; 
    struct ib_connection *remote_connection; 
    struct ibv_device *ib_dev; 

}; 

當我嘗試從而將其初始化:

struct app_data data = 
{ 
    .port = 18515, 
    .ib_port = 1, 
    .size = 65536, 
    .tx_depth = 100, 
    .sockfd = -1, 
    .servername = NULL, 
    .remote_connection = NULL, 
    .ib_dev = NULL 
}; 

我得到這個錯誤:

sorry, unimplemented: non-trivial designated initializers not supported 

我認爲它想要按照聲明的順序進行初始化,並且缺少local_connection。我不需要初始化它,並將其設置爲NULL不起作用。

如果我將其更改爲這對G ++,仍然得到同樣的錯誤:

struct app_data data = 
{ 
    port : 18515, 
    ib_port : 1, 
    size : 65536, 
    tx_depth : 100, 
    sockfd : -1, 
    servername : NULL, 
    remote_connection : NULL, 
    ib_dev : NULL 
}; 
+0

我想你正在使用g ++來編譯這段代碼。如果是,請刪除「。」即.port成爲端口,.ib_port變爲ib_port。它應該在那之後編譯。 – Anon

+1

我使用g ++ 4.9.2(啓用了C++ 11),但刪除了。不起作用? 「端口未在此範圍內聲明」 – Ivan

+0

哦。忘了提及,請使用「:」而不是「=」例如端口:18515,併爲其他變量也做。 – Anon

回答

14

這並不相剋工作++。你基本上在C++中使用C結構。幾個方法來解決它。

1)刪除「。」初始化時將「=」更改爲「:」。

#include <iostream> 

using namespace std; 
struct ib_connection 
    { 
    int x; 
    }; 

    struct ibv_device 
    { 
    int y; 
    }; 

struct app_data 
{ 
    int port; 
    int ib_port; 
    unsigned size; 
    int tx_depth; 
    int sockfd; 
    char *servername; 
    struct ib_connection local_connection; 
    struct ib_connection *remote_connection; 
    struct ibv_device *ib_dev; 

}; 

int main() 
{ 

    struct app_data data = 
    { 
     port : 18515, 
     ib_port : 1, 
     size : 65536, 
     tx_depth : 100, 
     sockfd : -1, 
     servername : NULL, 

     local_connection : {5}, 
     remote_connection : NULL, 
     ib_dev : NULL 
    }; 

    cout << "Hello World" << endl; 

    return 0; 
} 

2)使用g ++ -X c。 (不推薦)或將此代碼放在extern C中[免責聲明,我沒有測試過這個]

+0

還要注意這段代碼不是可移植的(但會與g ++一起使用)。你在C++中使用C結構的原因是什麼?做一些內核/驅動程序實現? – Anon

+3

謝謝你的作品。順便說一下,這些點在C++中起作用。不知道爲什麼你建議「:」代替。至於C的用法,主要是我有C中的例子,我試圖將它移植到C++中。一心一意。 – Ivan

+0

@伊萬謝謝你+1。我不知道。嘗試「.port = 6000」,它的工作! – Anon

-1

還要注意,正如原始問題所述,成員表達式的順序很重要。我注意到如果我只想在前面的例子中初始化「size」,我需要在.port和.ib_port之前放置表達式。否則,我得到的錯誤「對不起,未實現:不平凡的指定初始化不支持」不是那麼直觀...

+0

這讀作爲對答案的評論,而不是對提問者問題的答覆。 – toonice

3

我已經注意到我的GCC編譯器有一些技巧接受.fieldname = value assigments,但只會編譯字段按照它們在結構中聲明的順序來進行。

我能夠以兩種方式初始化這個結構。具有名稱的名稱提高了可讀性,並降低了如果稍後更改結構字段順序時分配錯誤數據的風險。

//Declare struct 
typedef struct 
{ 
    uint32_t const * p_start_addr; 
    uint32_t const * p_end_addr; 
    fs_cb_t const callback;  
    uint8_t const num_pages; 
    uint8_t const priority; 
} fs_config_t; 

//Assign unnamed 
fs_config_t fs_config 
{ 
    (uint32_t*)0x00030000, // uint32_t const * p_start_addr; 
    (uint32_t*)0x00038000, // uint32_t const * p_end_addr;   
    fs_evt_handler,   // fs_cb_t const callback; 
    8,      // uint8_t const num_pages; 
    0xFE     // uint8_t const priority;    
}; 

//Assign to named fields 
static fs_config_t fs_config1 
{ 
    .p_start_addr = (uint32_t*)0x00030000, 
    .p_end_addr = (uint32_t*)0x00038000,    
    .callback = fs_evt_handler, 
    .num_pages = 8, 
    .priority = 0xFE     
};  

經驗法則是:

  1. 分配給.NAME =值字段
  2. 分配在他們那裏宣佈
  3. 包括在分配新建分配FY所有字段的順序
9

初始化的順序需要按照聲明的順序進行。

typedef struct FOO 
{ 
    int a; 
    int b; 
    int c; 
}FOO; 

FOO foo = {.a = 1, .b = 2}; // OK 
FOO foo1 = {.a = 1};   // OK 
FOO foo2 = {.b = 2, .a = 1}; // Error sorry, unimplemented: non-trivial designated initializers not supported 
FOO foo3 = {.a = 1, .c = 2}; // Error sorry, unimplemented: non-trivial designated initializers not supported 

我知道這意味着編譯器不支持面向名稱,亂序,成員初始化。

需要以舊式方式初始化結構。爲了清楚起見,我保留了變量名,但是我必須按順序對它們進行初始化,而不是跳過變量。

我可以停止初始化任何變量,但不能初始化變量。

+1

與接受的答案的聲明相反,這在g ++中不起作用,我成功地將g ++(5.3.0)與此答案中給出的解決方案(而不是使用「-X」)結合使用。 –

+0

這個答案適合我。我可以通過字段名初始化,但必須按照我聲明的順序進行。 – alc6379

0

不幸的是,C++不支持指定的初始化程序。 GCC仍然允許您使用它們(作爲擴展名),但您必須以與struct中列出的順序相同的順序初始化成員。

另一個解決方法是使用一個立即調用拉姆達:

constexpr fuse_operations fuse_ops = []{ 
    fuse_operations ops{}; 
    ops.destroy = wiifs_destroy; 
    ops.getattr = wiifs_getattr; 
    ops.access = wiifs_access; 
    // ... 
    return ops; 
}(); 

我個人比較喜歡這個方案,因爲它是完全標準的C++,它可以讓你初始化你想要的訂單字段,跳過你穿上那些」需要並默認初始化其餘部分。編譯器仍然是able to optimise this。請注意,這隻適用於C++ 17或更新版本。