2015-10-20 50 views
1

當我嘗試按原樣運行此代碼時,收到編譯器消息「error:incompatible types in return」。我在代碼中標記了錯誤的位置。如果我把這條線出來,那麼編譯器很高興。從結構函數返回不兼容的類型 - C

問題是我想返回一個值表示無效輸入到函數(在這種情況下調用f2(2)。)我只想要一個結構返回的數據,如果函數調用時不使用2作爲參數。

我覺得只有兩條路走是要麼:

  1. 使函數返回一個結構指針,而不是死的結構,但隨後我調用函數看起來有趣,因爲我必須改變yb到y-> b,並且由於在存儲器中獲取數據的額外步驟,操作可能會更慢。

  2. 分配額外內存,零字節填充它,並將返回值設置爲內存中該位置的結構。 (例如:return x[nnn];而不是return x[0];)。這種方法將使用更多的內存和一些處理來填充零字節。

最終,我正在尋找一種解決方案,從長遠來看,它將是最快和最乾淨的(在代碼方面)。如果我必須堅持使用->來解決元素的成員,那麼我想這是要走的路。

有沒有人有一個解決方案,使用最少的CPU功率?

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

    typedef struct{ 
    long a; 
    char b; 
    }ab; 

    static char dat[500]; 

    ab f2(int set){ 
     ab* x=(ab*)dat; 
     if (set==2){return NULL;} 
     if (set==1){ 
     x->a=1; 
     x->b='1'; 
     x++; 
     x->a=2; 
     x->b='2'; 
     x=(ab*)dat; 
     } 
     return x[0]; 
    } 

    int main(){ 
     ab y; 
     y=f2(1); 
     printf("%c",y.b); 
     y.b='D'; 
     y=f2(0); 
     printf("%c",y.b); 
     return 0; 
    } 

回答

4

如果您關心速度,它是具體實現。

注意,在Linux x86-64 ABI定義了struct的(精確地)標量成員(即,整數,雙精度,或指針,哪位所有適合在一個單一機器寄存器 - 但不是struct等..這是聚合數據)通過兩個寄存器返回(不通過堆棧),而且速度非常快。

BTW

 if (set==2){return NULL;} //wrong 

顯然是錯誤的。你可以編寫:

if (set==2) return (aa){0,0}; 

此外,

ab* x=(ab*)dat; // suspicious 

看起來很可疑,我(因爲你return x[0];更高版本)。不保證dat適合對齊(例如8或16字節),在某些平臺(特別是x86-64)上,如果dat未對齊,則至少會失去性能(實際上是undefined behavior)。

順便說一句,我建議總是與指令返回像return (aa){l,c};(其中l可轉化爲longc的表達式轉換爲char表達);這可能是最容易閱讀的,並且將被優化以加載兩個返回寄存器。

當然,如果您關心性能,出於基準測試的目的,您應該啓用優化(和警告),例如,如果使用GCC,則使用gcc -Wall -Wextra -O2 -march=native進行編譯;我的系統上(Linux的/用GCC 5.2的x86-64)的小功能

ab give_both(long x, char y) 
    { return (ab){x,y}; } 

編譯(與gcc -O2 -march=native -fverbose-asm -S)爲:

  .globl give_both 
     .type give_both, @function 
give_both: 
.LFB0: 
     .file 1 "ab.c" 
     .loc 1 7 0 
     .cfi_startproc 
.LVL0: 
     .loc 1 7 0 
     xorl %edx, %edx  # D.2139 
     movq %rdi, %rax  # x, x 
     movb %sil, %dl  # y, D.2139 
     ret 
     .cfi_endproc 

你會發現所有的代碼使用的寄存器,並沒有存儲器被用來在所有..

+0

什麼是標量成員?從物理學的角度來說,我知道標量是一個只有量值而不是方向的值。編程中的標量是什麼? –

+0

細節在ABI中給出。但是'int','double'和'char *'都是標量類型 –

1

我會使用的返回值作爲錯誤代碼,並且調用者傳遞一個指向他的struct如:

int f2(int set, ab *outAb); // returns -1 if invalid input and 0 otherwise 
+0

它可以工作,但是在x86-64上可能效率較低。看到我的答案爲什麼... –

相關問題