我有一个关于在用C语言编写的队列实现中使用varadic功能的问题。特别是我需要编写一个多推功能来将结构存储到队列中。
code_generator.h
typedef enum
{
NOP,
START, END,
ADD, MIN, MULT, DIV,
..., // others similar stuffs
LABEL,
LE, GE, LT, GT,
AND, OR,
DECREMENT
} p_operator;
typedef struct code
{
p_operator operator;
p_argument argument;
struct code * next;
} *p_code;
typedef struct queue
{
unsigned int length;
struct code * head;
struct code * tail;
} p_queue;
不要担心p_operator和p_argument,第一个是枚举,第二个是用于存储不同类型数据的典型联合。 我尝试了两种不同的实现,但没有人工作。
p_queue pqueue_push(p_queue queue, p_code code, ...)
{
p_code temp;
va_list vars;
va_start(vars, code);
printf("PUSH 1\n");
for(temp = code; temp != NULL; temp = va_arg(vars, p_code))
{
printf("PUSH 2 OPERATOR: %d\n", temp->operator);
if(queue.length == 0)
{
printf("PUSH 3\n");
queue.tail = queue.head = temp;
}
else
{
printf("PUSH 4\n");
p_code swap = queue.tail;
swap->next = temp;
queue.tail = swap->next;
}
queue.length = queue.length + 1;
printf("PUSH 5 : %d\n", queue.length);
}
printf("PUSH 6\n");
va_end(vars);
return queue;
}
在这种情况下,程序打印所有内容,但循环再次执行(为什么?),显然,在队列中存储一些不存在的东西。
p_queue pqueue_push(p_queue queue, int nargs, p_code code, ...)
{
int i;
p_code temp;
va_list vars;
va_start(vars, code);
printf("PUSH 1 ARGS SIZE: %d\n", nargs);
for(i = 0; i < nargs; i++)
{
temp = va_arg(vars, p_code);
printf("PUSH 2 OPERATOR: %d\n", temp->operator);
if(queue.length == 0)
{
printf("PUSH 3\n");
queue.tail = queue.head = temp;
}
else
{
printf("PUSH 4\n");
p_code swap = queue.tail;
swap->next = temp;
queue.tail = swap->next;
}
// Aumenta la dimensione dello queue
queue.length = queue.length + 1;
printf("PUSH 5 : %d\n", queue.length);
}
printf("PUSH 6\n");
va_end(vars);
return queue;
}
在第二种情况下,控制台会在"PUSH 2"
显示细分错误,这意味着temp->operator
为NULL
(但如果第一种方法有效,它就没有任何意义相同的参数很好。)
这段代码是我在我的主要功能中运行的(我不认为你需要知道所有的依赖,原型等):
p_stack stack_temp = pstack_constructor();
// method 1
pstack_push(stack_temp, pcode_constructor_op(START));
// or method 2
pstack_push(stack_temp, 1, pcode_constructor_op(START));
结果方法1
OPERATOR 1
PUSH 2 OPERATOR: 1
PUSH 3
PUSH 4
PUSH 5
PUSH 2 OPERATOR: 1398167381
PUSH 4
PUSH 5
PUSH 6
分段错误(核心转储)
结果方法2
OPERATOR 1
PUSH 1 ARGS SIZE: 1
Segmentation fault (core dumped)
代码中使用的其他功能
p_queue pqueue_constructor()
{
p_queue queue;
queue.length = 0;
queue.head = queue.tail = NULL;
return queue;
}
p_code pcode_constuctor()
{
p_code code = ((p_code) malloc(sizeof(struct code)));
code->operator = NOP;
code->next = NULL;
return code;
}
p_code pcode_constructor_op(p_operator operator)
{
p_code code = pcode_constuctor();
code->operator = operator;
printf("OPERATOR %d\n", code->operator);
return code;
}
p_queue
和p_code
始终是inizializated va_arg(vars, p_code)
不要&#39;改变一切答案 0 :(得分:2)
对于第一个版本,它依赖于有一个NULL
指针来终止参数列表,并且你不会在调用中提供这样的终止NULL
指针意味着你将超越传递的参数时,未定义的行为。
解决方案非常简单,只需在调用中添加NULL
指针:
pstack_push(stack_temp, pcode_constructor_op(START), NULL);
对于第二个版本中的崩溃,您忘记了您应该使用的第一个p_code
参数是code
参数,并且您应该只在循环中获得下一个参数,就像您一样做第一个功能。
这意味着您取消引用的p_code
指针是传递的第二个 p_code
指针,但是您没有传递第二个指针导致未定义的行为,崩溃。