例如,以此示例函数为例:
#include <stdlib.h>
#define MAX 100
typedef struct stack {
int sp;
int val [MAX];
} STACK;
void initStack (STACK *s){
s->sp = 0;
}
int push (STACK *s, int x){
if(s->sp == MAX) return -1;
else s->val[s->sp++] = x;
return 0;
}
int main(){
STACK s;
int pushval, p;
initStack(&s);
p = push(&s, 1);
pushval = s.val[s.sp-1];
printf("pushval %d\n", pushval);
return 0;
}
所以在这种情况下,如果我做s.val [s.sp],我会得到胡言乱语。如果我做s.val [s.sp-1]我得到了我推到堆栈的值。我不知道堆栈指针是否应指向&#34;下一个可用空间&#34;又名等于数组中元素的数量,或应该等于数组的最后一个元素的索引,又名数组中的元素数 - 1
答案 0 :(得分:3)
这只是一个惯例问题。许多实现允许顶部堆栈指针指向&#34;下一个可用空间&#34;,但是你可以真正做你喜欢的事情,前提是你的堆栈外部表现得有意。
答案 1 :(得分:1)
对我来说,基于数组的堆栈最自然的实现是“向下”增长,堆栈指针指向最近推送的元素:
void initStack (STACK *s)
{
s->sp = MAX;
}
int push (STACK *s, int x)
{
if( !s->sp )
return 0;
else
s->val[--s->sp] = x;
return 1;
}
int pop(STACK *s, int *x)
{
if ( s->sp == MAX )
return 0;
else
*x = s->val[s->sp++];
return 1;
}
检查是更简单的IMO,并且因为它永远不会减少到0以下,你可以安全地使用无符号类型作为堆栈指针(我倾向于这样做可能不是完全合理的原因)。
请注意,这模仿了x86(和许多其他架构的)堆栈行为,因为SP向下“向下”,朝向0增长。
请注意,我在成功和失败时更改了返回值,因为在C 0
中表示“false”,非零表示“true”。这样你就可以编写像
if ( push( stack, val ) )
{
...
}
else
{
// push failed, handle as appropriate
}
同样,这只是一个更自然的IMO实现。