2013-02-05 174 views
1

对不起,我不能支持我的问题与一些代码(我不知道如何构造它,因此它会被接受在这里),但我仍然尝试。指向堆栈

如果我理解正确,那么引用相同类型结构的结构将需要使用包含的指针进行引用。这个指针可以引用堆栈上的分配空间(而不是堆)而不会产生分段错误? -

这应该如何声明?

+0

当你声明时,你不需要做任何特殊的事情。指针是否指向堆栈,堆或NULL对包含它的结构的声明没有影响。 –

回答

0

是的,你可以使用堆栈指针上的变量,但只有当还没有恢复提供该堆栈帧的方法。例如,这将工作:

typedef struct 
{ 
    int a; 
    float b; 
} s; 

void printStruct(const s *s) 
{ 
    printf("a=%d, b=%f\n", s->a, s->b); 
} 

void test() 
{ 
    s s; 
    s.a = 12; 
    s.b = 34.5f; 
    printStruct(&s); 
} 

这将导致错误然而,由于堆栈帧就会消失:

s *bad() 
{ 
    s s; 
    s.a = 12; 
    s.b = 34.5f; 
    return &s; 
} 

编辑:嗯,我说,这将导致一个错误,但在调用该代码:

int main() 
{ 
    test(); 
    s *s = bad(); 
    printStruct(s); 
    return 0; 
} 

我在编译过程中得到一个警告

s.c:27:5: warning: function returns address of local variable [enabled by default] 

和程序似乎很好地工作:

$ ./s 
a=12, b=34.500000 
a=12, b=34.500000 

但是,事实上,破碎。

+0

谢谢你的回答。我相信我明白为什么它应该被打破 - 但为什么它仍然有效? – stian

+0

这很可能是因为堆栈没有被重用*,因为函数返回了,所以之前的所有东西仍然有效。如果其他函数(使用堆栈变量)被调用,那么它肯定会失败。 – trojanfoe

0

你没有说什么语言你的工作中,所以假设下,现在从你的问题的措辞...下面的代码是完全合法:

typedef struct str_t_tag { 
    int foo; 
    int bar; 
    struct str_t_tag *pNext; 
} str_t; 

str_t str1; 
str_t str2; 
str1.pNext = &str2; 

在这个例子中都str1和str2在堆栈中,但如果其中一个或两个堆在一起,这也可以工作。唯一需要注意的是堆栈变量在超出作用域时会被跳过,所以如果你已经动态分配了str1并将它从一个函数中传回来,你不希望str1-> pNext指向在该函数中堆栈中的东西。

换句话说,不要做:

typedef struct str_t_tag { 
    int foo; 
    int bar; 
    struct str_t_tag *pNext; 
} str_t; 

str_t *func(void) 
{ 
    str_t *pStr1 = malloc(sizeof(*pStr1)); 
    str_t str2; 
    pStr1->pNext = &str2; 

    return pStr1; /* NO!! pStr1->pNext will point to invalid memory after this */ 
} 
+0

如果'pStr1'未初始化(如处理'malloc'行时的情况那样)'sizeof(* pStr1)'会工作吗? – Dukeling

+0

yes - sizeof在编译时会被忽略,并且不需要初始化内容以知道它们的大小。 – Vicky

0

不知道这是否是特别的C/C++问题,但我会以C/C++代码为例。

的唯一方法可以声明它:(有少许变化)

typedef struct abc 
{ 
    struct abc *other; 
} abc; 

other可以指向一个物体在栈上,如下所示:

abc a, b; // stack objects 
b.other = &a; 

这不是一个大约范围问题,所以我会跳过评论上述做法的可能问题。

但是,如果要将其分配给动态创建的对象,则该对象无法位于堆栈上。

abc b; 
b.other = malloc(sizeof(abc)); // on the heap 
+0

伟大而详细的答案:) – stian

+1

@dexter,如果这个或其他答案帮助你,那么请upvote它(使用答案左侧的向上箭头)和/或接受它(使用绿色的勾号,也可以答案左侧)。 – Vicky

+0

@vicky,obs,对不起。 – stian