2016-11-27 59 views
1

我試圖做一個函數來初始化一個結構並將其傳回給它的返回值,但是我無法讓它工作。我在哪裏犯了一個錯誤?我收到了分段錯誤錯誤。通過函數的返回值來初始化C結構體

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

typedef struct { 
    int id; 
    char *name; 
} Object; 

Object object_ctor(int id, char *name); 

int main() 
{ 
    Object x; 

    x = object_ctor(1, "Alex"); 

    printf("%s\n", x.name); 
    return 0; 
} 

Object object_ctor(int id, char *name) 
{ 
    Object y; 
    y.id = id; 
    y.name = *name; 

    return y; 
} 
+0

Y是本地堆棧。功能退出時不再使用。需要使用堆 – OldProgrammer

+0

您正在取消引用'object_ctor'的名稱。不要這樣做。儘管你可能想要使用'strdup(name)'或類似的東西,所以你有一個堆分配版本的字符串,因爲如果你從另一個函數調用'object_ctor',指針可能指向一個分配給它的字符串堆棧(即不再存在)。 – Goodies

+3

@OldProgrammer:完全可以返回一個局部變量(副本),例如一個結構體。不允許的是返回一個指向局部變量的指針。如果函數返回一個「Object *」,那麼你的擔心是合法的。 –

回答

2

我在哪裏犯了一個錯誤?

這是該行:

y.name = *name; 

這是錯誤的兩個原因。

  1. 您正在分配char,​​,以char*類型,y.name的變量。它違反了指針運算符對指針的約束。

    從C11標準:

    6.5.16.1簡單賦值

    約束

    1下列情況之一的應持有:

    ...

    - 左操作數具有原子,限定或非限定指針類型,並且(考慮左值操作數在左值轉換後會有的類型),兩個操作數都是指向兼容類型的限定版本或非限定版本的指針,而左邊指向的類型具有由右側指向的所有類型的限定符;

    - 左操作數具有原子性,限定性或非限定性指針類型,並且(考慮左操作數在左值轉換後將具有的類型)一個操作數是指向對象類型的指針,另一個是指向void的合格或不合格版本,左側指出的類型具有右側指向的所有類型的限定符;

    - 左操作數是原子,限定或非限定指針,右是空指針常量;或

    該分配的RHS不滿足任何上述約束。

  2. 當你對待

    printf("%s\n", x.name); 
    

    該值作爲空終止字符串,你碰到不確定的行爲。

通過調出編譯器的警告級別,可以檢測出類似的錯誤。與gcc -Wall一起編譯時,我會得到以下結果。

soc.c: In function ‘object_ctor’: 
soc.c:26:12: warning: assignment makes pointer from integer without a cast [-Wint-conversion] 
    y.name = *name; 
      ^

你需要使用類似:

y.name = strdup(name); 

如果strdup不可用你的平臺上,這不是太難以執行。您也可以在網絡上輕鬆找到實現。

+0

請注意''strdup()'通常使用'malloc()'這意味着你需要釋放它。也許一個'object_dtor'函數可以'釋放''從'strdup()'分配的內存。 – Goodies

+0

謝謝你,爲我工作:) – Zeusko

+0

我也試過這個:y.name = name;它的工作,這怎麼可能? – Zeusko