从C中的数组堆栈弹出 - 将NULL分配给int *

时间:2016-07-07 12:23:57

标签: c arrays pointers

考虑以下堆栈数组的定义:

typedef struct larray{
    int values[BSize];
    struct larray *prox;
}*LArrays;

typedef struct stack{
    int sp; //number of occupied positions in stack's top array
    LArrays s; //stack top
}Stack;

我写了这个pop函数:

int pop(Stack *st, int *t){
    if (st->sp == 0) return -1;

    if (st->sp == 1){
        LArrays newTop = st->s->prox;
        free(st->s);
        st->s = NULL;
        st->s = newTop;
        st->sp = BSize;
        return 0;
    }

    LArrays l = st->s;
    int *remover = l->values + (--st->sp);  
    *t = *remover;
    *remover = NULL;

    return 0;
}

有效。但是在编译时,gcc产生了这个警告:

  

警告:赋值在没有强制转换的情况下从指针生成整数[-Wint-conversion]

     *remover = NULL;

为int *?

分配NULL是错误的

[更改为去除后的结果= NULL]

主:

for (; i < 150; i++)
        push(stack,i);
    i = 0;

    printStack(stack);

    for (; i < 70; i++)
        pop(stack,&r);

    printStack(stack);
  

with * remover = NULL(产生所需的输出!)

//stack after push

100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|]

---------------------------------------------------------
0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|]

//stack after pop
0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|]
  

with remover = NULL(不产生所需的输出!)

//stack after push

100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|]

---------------------------------------------------------
0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|]


//stack after pop
0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|]

打印功能:

void printArray(int *v, int N){
    int *p = v;
    int i = 0;
    for(; i < N; i++)
        printf("%d|",*p++);
    printf("]\n\n");
}

void printStack(Stack *stack){
    LArrays p = stack->s;
    printf("Free Space on Stack's head: %d\n",BSize - stack->sp);
    printf("\nStack:\n\n");
    while(p->prox != NULL){
        printArray(p->valores,BSize);
        printf("------------------------------------------------\n");
        p = p->prox;
    }printArray(p->values,BSize);
}

6 个答案:

答案 0 :(得分:1)

没有错误NULL分配给int *,但将其分配给int并不总是正确的。它是实现定义的行为。

详细说明,NULL

  

NULL

     

扩展为实现定义的空指针常量; [...]

然后,引用章节§6.3.2.3/ p6(强调我的

  

任何指针类型都可以转换为整数类型。除了之前指定的,   结果是实现定义的。如果结果无法以整数类型表示,   行为未定义。

所以,你的编译器会警告你。

看起来,在这里,你只是误解了如何使用指针变量。你不需要去取消引用。你需要改变

 *remover = NULL;

remover = NULL;   // assign NULL to the pointer variable, not to the value it points to.

摆脱警告。

答案 1 :(得分:1)

您没有为int *分配NULL。您将其分配给int

remover的类型为int *,而*remover取消引用该指针且类型为int

将该行更改为以下内容:

remover = NULL;

实际上,您可以完全删除该行,因为在该点之后未引用remover

答案 2 :(得分:1)

您要将NULL分配给int *,而不是int。您执行*remover = NULL;removerint **remover为int。

答案 3 :(得分:1)

这不是警告所说的。它表示*remover = NULL正在将指针(NULL)分配给整数(*remover)(请参阅您的声明,它说“*removerint” )。

您是否要将NULL分配给名为int *的{​​{1}},请执行以下操作:

remover

这是完全合法的。

答案 4 :(得分:1)

  

将NULL分配给int *?

是错误的

不,这样做是有效的。

然而,这不是编译器所抱怨的。

仔细阅读信息(人们应该做什么,BTW; - ):

warning: assignment makes integer from pointer without a cast [-Wint-conversion]
 *remover = NULL;

现在让我们分开警告:

... assignment makes integer ...

这转换为:“代码[尝试]分配给整数......

... from pointer ...

这转换为:“ ...来自指针(值)......

查看相关行:

 *remover = NULL;

我们看到*remover已分配,NULL是已分配的值。

将所有这些放在一起我们可以得出结论,编译器正在进行

*remover

是一个整数,

NULL

成为指针(值)。

加上“编译器永不失败”,你应该能够理解这个问题。

: - )

答案 5 :(得分:0)

您正在指定卸妆指向的值。如果要为指针指定NULL,请使用此指针。

remover = NULL;