如何在C中推和弹出一个空指针 [英] How to push and pop a void pointer in C

查看:95
本文介绍了如何在C中推和弹出一个空指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个工作代码:

#import <stdlib.h>
#import <stdio.h>

typedef struct myarray {
  int len;
  void* items[];
} MYARRAY;

MYARRAY *collection;

void
mypop(void** val) {
  puts(collection->items[collection->len]);
  *val = collection->items[collection->len--];
}

void
mypush(void* val) {
  int len = collection->len++;
  collection->items[len] = val;
  puts(collection->items[len]);
}

int
main() {
  puts("Start");
  collection = malloc( sizeof *collection + (sizeof collection->items[0] * 1000) );
  collection->len = 0;
  puts("Defined collection");
  mypush("foo");
  puts("Pushed foo");
  mypush("bar");
  puts("Pushed bar");
  char str1;
  mypop((void*)&str1);
  puts("Popped bar");
  puts(&str1);
  char str2;
  mypop((void*)&str2);
  puts("Popped foo");
  puts(&str2);
  puts("Done");
  return 0;
}

输出:

Start
Defined collection
foo
Pushed foo
bar
Pushed bar
(null)
Popped bar

bar
Popped foo
�ߍ
Done

应改为输出:

Start
Defined collection
foo
Pushed foo
bar
Pushed bar
bar
Popped bar
bar
foo
Popped foo
foo
Done

对于CI来说,不是很确定是怎么回事还是为什么输出结果是损坏。似乎双指针 void ** 允许您在不知道类型的情况下传入指针并获取值 ,所以是的。但是想知道是否可以显示该代码应如何实现,以便让我对如何做这样的事情有所了解。

Being new to C I am not really sure what's going on or why the output is "corrupted" like that. It seems though that the double pointer void** allows you to pass in a pointer and get out a value without knowing the type, so yay. But wondering if one could show how this code should be implemented so I can get a feel for how to do such a thing.

与clang编译:

clang -o example example.c






更新

我已更新代码以反映最新答案,但仍然不确定集合的malloc是否正确。

I've updated my code to reflect the latest answers, but still not sure the malloc of the collection is correct.

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

typedef struct myarray {
  int len;
  void* items[];
} MYARRAY;

MYARRAY *collection;

void
mypop(void** val) {
  --collection->len;
  puts(collection->items[collection->len]);
  *val = collection->items[collection->len];
}

void
mypush(void* val) {
  int len = collection->len++;
  collection->items[len] = val;
  puts(collection->items[len]);
}

int
main() {
  puts("Start");
  collection = malloc( sizeof *collection + (sizeof collection->items[0] * 1000) );
  collection->len = 0;
  puts("Defined collection");
  mypush("foo");
  puts("Pushed foo");
  mypush("bar");
  puts("Pushed bar");
  char *str1;
  mypop((void**)&str1);
  puts("Popped bar");
  puts(str1);
  char *str2;
  mypop((void**)&str2);
  puts("Popped foo");
  puts(str2);
  free(collection);
  puts("Done");
  return 0;
}


推荐答案

有些事情要修复,但对于初学者来说还不错。

There are a few things to fix, but for a beginner that is not bad.


  1. pop

您需要先减小 len (您的推送在增加之后正确执行)。这是一个堆栈。

You need to decrement first len (your push does correctly post-increment). This is a stack.

void mypop(void** val) {
     puts(collection->items[--collection->len]);
     *val = collection->items[collection->len];
}

数组从 0 ,因此

len = 0;
items[len++] = elem1;  // len is 0 for the assignment then incremented
items[len++] = elem2;  // len is 1 for the assignment then incremented

然后弹出值

elem2 = items[--len];  // len is first decremented to 1
elem1 = items[--len];  // len is first decremented to 0




  1. str

您想要的是一个指向chars的指针,一个 char * str1 str2 ,因为 pop()将存储一个

What you want is a pointer to chars, a char *, for str1 and str2, since pop() will store a pointer, not a single char.

 char *str1;
 mypop((void **)&str1);
 puts("Popped bar");
 puts(str1);
 char *str2;
 mypop((void **)&str2);
 puts("Popped foo");
 puts(str2);
 puts("Done");
 return 0;

这应该可以修复明显损坏的显示。但是还有更多有趣的事情

That should fix the visibly corrupted display. However there are a few more things of interest


  1. 分配

您的程序之所以运行是因为您的分配量很大,并且结构,整个分配可能会覆盖其空间。但这做出了一个假设(很可能是公平的),这可能会导致未定义行为在某些情况下。

Your programs runs because your allocation is big, and items being inside the struct, its space is likely covered by the whole allocation. But that makes an assumption (quite likely, to be fair), which could lead to undefined behavior in some situations.

但是为了更加简洁,因为您有两个实体要分配,所以需要两个分配

But to be cleaner, since you have two entities to allocate, that needs two allocations

collection = malloc( sizeof *collection );
collection->items = malloc( sizeof(collection->items[0]) * 1000 );

稍后都将被释放。

在这种情况下,结构应为

In this case, the structure should be

typedef struct myarray {
  int len;
  void **;
} MYARRAY

MYARRAY 本身很小,您也可以静态声明它。

Since MYARRAY itself is pretty small, you could also declare it statically

static MYARRAY collection;




  1. import

#import 已过时,请使用 #include 代替。

#import is deprecated, please use #include instead.

这篇关于如何在C中推和弹出一个空指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆