问题描述
以下代码是我的大型程序的简化版本,用于演示问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const int m = 5;
char **words1;
char **words2;
void f(void *v) {
printf("v: %p\n",v);
int len = v==words1 ? 3 : 4;
printf("len: %d\n",len);
for (int i=0; i<m; i++) {
// What goes here?
/*
char *c = malloc(sizeof(char) * len);
c = (char*)v; // Something _like_ this?!
printf("%s\n",c);
*/
}
}
int main(int argc,char *argv[]) {
words1 = malloc(m * sizeof(char*));
printf("%p\n",words1);
words2 = malloc(m * sizeof(char*));
printf("%p\n",words2);
for (int i=0; i<m; i++) {
words1[i] = malloc(sizeof(char) * 3);
words2[i] = malloc(sizeof(char) * 4);
strcpy(words1[i],"22");
strcpy(words2[i],"333");
}
f(words1);
f(words2);
for (int i=0; i<m; i++) {
free(words1[i]);
free(words2[i]);
}
free(words1);
free(words2);
}
我有两个全局 **char
,我认为在堆上(因为 malloc
)。
f()
的签名不能改变,即只能接受void *
。
重要的是,在实际程序中,**char
中的数据对于堆栈来说太大了。
简而言之:如何从 **char
取回 *void
?
解决方法
您可以简单地在 f()
中将其分配给正确的类型:
char **f_words = v;
for (int i=0; i<m; i++) {
printf("%s\n",f_words[i]);
}
此外,您识别 f()
中单词长度的方法也不好。
您可以将长度作为附加参数传递给 f()
,也可以使用 NULL
指针终止单词列表。
考虑将 struct
后面的内容传递给 f()
。它将使获取 len
、m
和 words
更加清晰并且没有全局变量。
struct S {
int len;
int m;
char **words;
};
void f(void *v) {
struct S *s = v;
int len = s->len;
int m = s->m;
char **word = s->words;
printf("v: %p\n",v);
printf("len: %d\n",len);
for (int i = 0; i < m; i++) {
printf("%s\n",words[i]);
}
int main(int argc,char *argv[]) {
...
// passing a pointer to compound literal
f(&(struct S){ 3,m,words1});
f(&(struct S){ 4,words2});
...
}