2016-11-27 63 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