我们遇见过 发表于 2018-10-3 23:30:47

链式队列的一个问题,为什么第一种可以运行,第二种没有报错但是运行会中断

第一种:
typedef struct Qnode//队列结点定义
{
int data;
Qnode * next;
}Qnode;

typedef struct Lq//链队类型定义
{
Qnode * front;
Qnode * rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
if(qu->front==NULL||qu->rear==NULL)
{
          
       
          return true;
}
else
          return false;
}

void init(Lq * &qu)//初始化
{
qu=(Lq *)malloc(sizeof(Lq));
(*qu).front=(*qu).rear=NULL;
printf("初始化成功!\n");
}


void in_qu(Lq * qu,int a)//入队
{
Qnode *s;
s=(Qnode*)malloc(sizeof(Qnode));
s->next=NULL;
s->data=a;

          if(is_empty(qu))
          {
                  qu->front=qu->rear=s;

          }
          else
          {
          qu->rear->next=s;
                qu->rear=s;
          }
          return;
}
void out_qu(Lq *qu)//出队
{
Qnode * p;
int a;
if(is_empty(qu))
{
    printf("队空不能出队!\n");
        return;
}
p=qu->front;
a=qu->front->data;
qu->front=p->next;
if(qu->front==NULL)//即队列中只有一个元素
          qu->rear=NULL;
free(p);
printf("出队的元素是:%d\n",a);
return;
}

void out_qu(Lq *qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq * & qu);

int main()
{
Lq qu;
Lq * p;
p=&qu;
init(p);
in_qu(p,1);
out_qu(p);
return 0;

}



第二种:
typedef struct Qnode//队列结点定义
{
int data;
Qnode * next;
}Qnode;

typedef struct Lq//链队类型定义
{
Qnode * front;
Qnode * rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
if(qu->front==NULL||qu->rear==NULL)
{
          
       
          return true;
}
else
          return false;
}

void init(Lq * &qu)//初始化
{
qu=(Lq *)malloc(sizeof(Lq));
(*qu).front=(*qu).rear=NULL;
printf("初始化成功!\n");
}


void in_qu(Lq * qu,int a)//入队
{
Qnode *s;
s=(Qnode*)malloc(sizeof(Qnode));
s->next=NULL;
s->data=a;

          if(is_empty(qu))
          {
                  qu->front=qu->rear=s;

          }
          else
          {
          qu->rear->next=s;
                qu->rear=s;
          }
          return;
}
void out_qu(Lq *qu)//出队
{
Qnode * p;
int a;
if(is_empty(qu))
{
    printf("队空不能出队!\n");
        return;
}
p=qu->front;
a=qu->front->data;
qu->front=p->next;
if(qu->front==NULL)//即队列中只有一个元素
          qu->rear=NULL;
free(p);
printf("出队的元素是:%d\n",a);
return;
}
void out_qu(Lq *qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq * & qu);

int main()
{
Lq qu;
init(&qu);
in_qu(&qu,1);
out_qu(&qu);
return 0;

}

claws0n 发表于 2018-10-3 23:37:33

呃,有点长……没仔细看
第二种 Lq qu; 本身是一个结构体,不是指针,而你在 init 的时候却把它当指针使用
第一种的 qu 没有实质的作用吧

我们遇见过 发表于 2018-10-3 23:42:34

claws0n 发表于 2018-10-3 23:37
呃,有点长……没仔细看
第二种 Lq qu; 本身是一个结构体,不是指针,而你在 init 的时候却把它当指针使用 ...

第二种里面 直接用&取地址不是一样吗..我看视频的时候记得那老师说指针就是地址- -

claws0n 发表于 2018-10-3 23:58:18

我们遇见过 发表于 2018-10-3 23:42
第二种里面 直接用&取地址不是一样吗..我看视频的时候记得那老师说指针就是地址- -

你什么编译器?
typedef struct Qnode//队列结点定义
{
int data;
struct Qnode * next;
}Qnode;

不一样哦,取址只有右值,指针参考的是左值,可以解引用得到右值
指针、取址、数组,很多时候可以互换,但是它们是不一样的东西

我们遇见过 发表于 2018-10-4 00:07:48

claws0n 发表于 2018-10-3 23:58
你什么编译器?
typedef struct Qnode//队列结点定义
{


好晕- -我之前typedef那个是你写的那样定义的,后来看课本里这样定义了就用这个了,我上面那个第二种贴错了,那个编译器会报错,但是
void out_qu(Lq *qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq *qu);

int main()
{
Lq qu;
init(&qu);
in_qu(&qu,1);
out_qu(&qu);
return 0;

}
这个不会报错,但是运行会中断,但是,我把 in 和 out那个注释之后,只有init这一句就不会中断..这种情况他们不是都一样的吗..为什么一个会中断一个不会。。

我们遇见过 发表于 2018-10-4 00:08:27

claws0n 发表于 2018-10-3 23:58
你什么编译器?
typedef struct Qnode//队列结点定义
{


用的vc6.0- -考试要求用这个{:10_266:}

claws0n 发表于 2018-10-4 00:48:56

本帖最后由 claws0n 于 2018-10-4 01:21 编辑

我们遇见过 发表于 2018-10-4 00:07
好晕- -我之前typedef那个是你写的那样定义的,后来看课本里这样定义了就用这个了,我上面那个第二种贴错 ...

vc6.0 ...... 加油{:10_250:}
编译器:MinGW GCC 8.10 64位   状态:没问题
编译器:Borland C++ 64位         状态:没问题
编译器:TDM GCC 4.9.264位    状态:没问题
编译器:TDM GCC 4.9.232位    状态:卡……
问题:is_empty 判断错误,去到 else
原因不明{:10_282:}
还是那一句,不是指针就不要当指针用,也许 64 位的指针有 8 个字节,刚好够装你的单一测试数据

@人造人 ,反编译能看出吗?

我们遇见过 发表于 2018-10-4 01:07:31

claws0n 发表于 2018-10-4 00:48
vc6.0 ...... 加油
编译器:MinGW GCC 8.10 64位   状态:没问题
编译器:Borland C++ 64位...

其实还有个题,就是我调试的时候也发现那个isempty莫名其妙跳到else了,然后我看答案,答案里那个init里的参数用的引用型,然后用引用型的话...我都不知道咋说了。。就是用引用型的话,主函数里的那个,该传入什么类型啊。。就是说函数定义是void init(Lq * & qu),那么主函数里写成init(&qu)为什么会报错啊,如果函数定义成void init(Lq * qu),主函数里那样写就不会报错。。

人造人 发表于 2018-10-4 01:39:41

claws0n 发表于 2018-10-4 00:48
vc6.0 ...... 加油
编译器:MinGW GCC 8.10 64位   状态:没问题
编译器:Borland C++ 64 ...

claws0n 发表于 2018-10-4 02:05:50

人造人 发表于 2018-10-4 01:39


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

typedef struct Qnode//队列结点定义
{
        int data;
        Qnode* next;
}Qnode;

typedef struct Lq//链队类型定义
{
        Qnode* front;
        Qnode* rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
        printf("%d\n", sizeof(qu));
        if (qu->front == NULL || qu->rear == NULL)
                return true;
        else
                return false;
}

void init(Lq * qu)//初始化
{
        qu = (Lq *)malloc(sizeof(Lq));
        (*qu).front = (*qu).rear = NULL;
        printf("初始化成功!\n");
}


void in_qu(Lq *qu, int a)//入队
{
        Qnode *s;
        s = (Qnode*)malloc(sizeof(Qnode));
        s->next = NULL;
        s->data = a;
        printf("in\n");
        if (is_empty(qu))
        {
                printf("2\n");
                qu->front = qu->rear = s;
        }
        else
        {
                printf("3\n");
                qu->rear->next = s;
                printf("4\n");
                qu->rear = s;
        }
        printf("in2\n");
        return;
}

void out_qu(Lq *qu)//出队
{
        Qnode *p;
        int a;
        if (is_empty(qu))
        {
                printf("队空不能出队!\n");
                return;
        }
        p = qu->front;
        a = qu->front->data;
        qu->front = p->next;
        if (qu->front == NULL)//即队列中只有一个元素
                qu->rear = NULL;
        free(p);
        printf("出队的元素是:%d\n", a);
        return;
}

void out_qu(Lq *qu);
void in_qu(Lq *qu, int a);
bool is_empty(Lq *qu);
void init(Lq *qu);

int main()
{
        Lq qu;
        init(&qu);
        printf("1\n");
        in_qu(&qu, 1);
        printf("12\n");
        out_qu(&qu);
        return 0;

}

人造人 发表于 2018-10-4 02:19:01

claws0n 发表于 2018-10-4 02:05


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

typedef struct Qnode//队列结点定义
{
        int data;
        Qnode* next;
}Qnode;

typedef struct Lq//链队类型定义
{
        Qnode* front;
        Qnode* rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
        printf("%d\n", sizeof(qu));
        if(qu->front == NULL || qu->rear == NULL)
                return true;
        else
                return false;
}

// 初始化
void init(Lq *qu)
{
        qu = (Lq *)malloc(sizeof(Lq));
        (*qu).front = (*qu).rear = NULL;
        printf("初始化成功!\n");
}


void in_qu(Lq *qu, int a)//入队
{
        Qnode *s;
        s = (Qnode*)malloc(sizeof(Qnode));
        s->next = NULL;
        s->data = a;
        printf("in\n");
        if(is_empty(qu))
        {
                printf("2\n");
                qu->front = qu->rear = s;
        }
        else
        {
                printf("3\n");
                qu->rear->next = s;
                printf("4\n");
                qu->rear = s;
        }
        printf("in2\n");
        return;
}

void out_qu(Lq *qu)//出队
{
        Qnode *p;
        int a;
        if(is_empty(qu))
        {
                printf("队空不能出队!\n");
                return;
        }
        p = qu->front;
        a = qu->front->data;
        qu->front = p->next;
        if(qu->front == NULL)//即队列中只有一个元素
                qu->rear = NULL;
        free(p);
        printf("出队的元素是:%d\n", a);
        return;
}

void out_qu(Lq *qu);
void in_qu(Lq *qu, int a);
bool is_empty(Lq *qu);
void init(Lq *qu);

int main()
{
        Lq qu;

        Lq *tmp = &qu;
        printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
        init(&qu);
        printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
       
        printf("*******************************\n");
        qu.front = NULL;
        qu.rear = NULL;
        printf("front:%.8X, rear:%.8X\n", tmp->front, tmp->rear);
        exit(1);
       
        printf("1\n");
        in_qu(&qu, 1);
        printf("12\n");
        out_qu(&qu);
        return 0;

}


front:CCCCCCCC, rear:CCCCCCCC
初始化成功!
front:CCCCCCCC, rear:CCCCCCCC
*******************************
front:00000000, rear:00000000
请按任意键继续. . .

// 初始化
void init(Lq *qu)
{
        qu = (Lq *)malloc(sizeof(Lq));
        (*qu).front = (*qu).rear = NULL;
        printf("初始化成功!\n");
}

人造人 发表于 2018-10-4 02:28:53

claws0n 发表于 2018-10-4 02:05


#include <stdio.h>

void Fun1(int *n)
{
        n = 0;
}

void Fun2(int *n)
{
        *n = 0;
}

int main()
{
        int a = 10;
       
        printf("%.8X\n", a);
        Fun1(&a);
        printf("%.8X\n", a);
        printf("\n");

        printf("%.8X\n", a);
        Fun2(&a);
        printf("%.8X\n", a);

        return 0;

}


0000000A
0000000A

0000000A
00000000
请按任意键继续. . .

我们遇见过 发表于 2018-10-4 08:59:03

claws0n 发表于 2018-10-4 02:05


这个不还是不能运行吗。。可能编译器问题?{:10_266:}

我们遇见过 发表于 2018-10-4 09:01:04

人造人 发表于 2018-10-4 02:28


没看明白..是第一个函数没有改变a吗..

我们遇见过 发表于 2018-10-4 09:16:21

人造人 发表于 2018-10-4 02:19


这个执行init后front,rear为什么没改变啊..传入的是地址不应该改变了吗..

我们遇见过 发表于 2018-10-4 10:55:47

看了在csdn别人的解答,感觉相对清楚点吧,但还是没完全搞懂。。。有相同问题的朋友自行理解吧,同时谢谢楼上的两位大佬不辞辛苦大半夜在帮我解答,万分感谢

楼主,你要注意了。对于c++来说,除非传递引用(也就是你所谓正确的方式),否则在函数内修改一个变量,永远无法作用到实参上。
void init(Lq * qu)//初始化
{
qu=(Lq *)malloc(sizeof(Lq));
(*qu).front=(*qu).rear=NULL;
printf("初始化成功!\n");
}
这段代码,你虽然修改了qu,让qu指向你分配的内存。但是退出函数,
init(&qu);
这里的qu并不会改变。

请注意以下两个的区别:
(1)修改一个指针,让它指向另一个地址,这个不会作用到实际参数
(2)通过指针,修改其指向的内容。这个会作用到实际参数指向的内容,因为两者共享的是相同的内容。

因此,如果你要在函数内改变指针指向的内容,那么用指针就可以。要改变指针的指向,让它指向另一个地址,那么必须用指针的指针(2个指针)
此时对于第二个指针,它指向实际的内容,第一个指针,指向第二个指针,而你可以修改第一个指针的指向,从而将第二个指针指向的内容作用到调用者。

修改以后的程序:

#include "stdio.h"
#include "stdlib.h"

typedef struct Qnode//队列结点定义
{
int data;
Qnode * next;
}Qnode;

typedef struct Lq//链队类型定义
{
Qnode * front;
Qnode * rear;
}Lq;

bool is_empty(Lq *qu)//判断是否队空
{
if(qu->front==NULL||qu->rear==NULL)
{

return true;
}
else
return false;
}

void init(Lq ** qu)//初始化
{
*qu=(Lq *)malloc(sizeof(Lq));
(*qu)->front=(*qu)->rear=NULL;
printf("初始化成功!\n");
}

void in_qu(Lq * qu,int a)//入队
{
Qnode * s;
s=(Qnode *)malloc(sizeof(Qnode));
s->next=NULL;
s->data=a;

if(is_empty(qu))
{
      qu->front=qu->rear=s;

}
else
{
    qu->rear->next=s;
    qu->rear=s;
}
return;
}
void out_qu(Lq * qu)//出队
{
Qnode * p;
int a;
if(is_empty(qu))
{
printf("队空不能出队!\n");
return;
}
p=qu->front;
a=qu->front->data;
qu->front=p->next;
if(qu->front==NULL)//即队列中只有一个元素
qu->rear=NULL;
free(p);
printf("出队的元素是:%d\n",a);
return;
}
void out_qu(Lq * qu);
void in_qu(Lq * qu,int a);
bool is_empty(Lq *qu);
void init(Lq * qu);

int main()
{
Lq * qu;
init(&qu);
in_qu(qu,1);
out_qu(qu);
return 0;

}


注意我对main和init的修改。

claws0n 发表于 2018-10-4 11:43:50

我们遇见过 发表于 2018-10-4 10:55
看了在csdn别人的解答,感觉相对清楚点吧,但还是没完全搞懂。。。有相同问题的朋友自行理解吧,同时谢谢楼 ...

嗯,合理使用指针。
Lq *qu; //在 main 函数里,这个是重点
因为 void init(Lq **qu); 所以 init(&qu); 如果不是空型,可以用单指针。
之后所有的函数调用,数据类型吻合,都是指针
init 定义对,但声明错了,是双指针。

我们遇见过 发表于 2018-10-4 12:57:01

claws0n 发表于 2018-10-4 11:43
嗯,合理使用指针。
Lq *qu; //在 main 函数里,这个是重点
因为 void init(Lq **qu); 所以 init(&qu); ...

我又有问题了。。这个双指针这个我明白了,但是没明白引用。。
void init(Lq * & qu);
init(&qu);main函数中只运行这一句,这个会直接报错,,错误信息cannot convert parameter 1 from 'struct Lq *' to 'struct Lq *& ',
用这个是正确的Lq qu; Lq * p; p=&qu; init(p);,正确的这个里面不也是 from 'struct Lq *' to 'struct Lq *& '吗,,为什么一个可以一个不可以啊。。

claws0n 发表于 2018-10-4 13:17:36

我们遇见过 发表于 2018-10-4 12:57
我又有问题了。。这个双指针这个我明白了,但是没明白引用。。
void init(Lq * & qu);
init(&qu);main ...

你说的是第一种和第二种吗?
数据类型不匹配。第一种正确,p 是指针,你引用了,那个 & 不是取址。
第二种,qu 不是指针,函数不会帮你转

我们遇见过 发表于 2018-10-4 14:20:32

claws0n 发表于 2018-10-4 13:17
你说的是第一种和第二种吗?
数据类型不匹配。第一种正确,p 是指针,你引用了,那个 & 不是取址。
第 ...

不明白...抛开这道题int*p=&q,将p作为一个参数传入另一个函数,与,直接将&q作为一个参数传入另一个函数不一样吗
页: [1] 2 3
查看完整版本: 链式队列的一个问题,为什么第一种可以运行,第二种没有报错但是运行会中断