用C编写一个通用的功能,如何处理字符串 [英] Writing a generic function in C, how to handle strings

查看:95
本文介绍了用C编写一个通用的功能,如何处理字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,需要一个无效** 参数和一个整数,指示其数据类型

I have a function that takes a void** argument and an integer that indicates its datatype

void foo (void** values, int datatype)

在函数内部,根据不同的数据类型,我这样的malloc吧:

Inside the function, depending on the datatype, I malloc it this way:

if (datatype == 1)
    *values = (int*) malloc (5 * sizeof(int));
else if (datatype == 2)
    *values = (float*) malloc (5 * sizeof(float));

所有这些都是好的,现在高达。然而,当字符串进入图片,事情就变得复杂了。在无效** 将需要无效*** ,因为我需要做这样的事情:

All is good upto now. However, when character strings come into the picture, things get complicated. The void** would need to be void***, since I will need to do something like this:

*values = (char**) malloc (5 * sizeof(char*));
for(i=0;i<5;i++)
    (*values)[i] = (char*) malloc (10);
..
strncpy( (*values)[0], "hello", 5);

应该如何这样的情况如何处理?
我可以通过一个字符*** 给需要的功能的无效** ,但投它正确里面呢?

How should such a situation be handled? Can I pass a char*** to the function that expects a void** but cast it correctly inside it?

void foo (void** values, int datatype) {

if(datatype == 3) {
    char*** tmp_vals = (char***) values;
    *tmp_vals = (char**) malloc (5 * sizeof(char*));
    ...
    (*tmp_vals)[i] = (char*) malloc (10 * sizeof(char));
    strncpy (  (*tmp_vals)[i], "hello", 5);
}

于是我就投了无效** 字符*** 。我尝试这样做,忽略了警告,它工作得很好。
但是,这是安全的吗?有没有更优雅的替代方案?

So I just cast the void** into a char***. I tried this and ignoring the warnings, it worked fine. But is this safe? Is there a more graceful alternative?

推荐答案

您不需要(可能不应该)使用无效** 在所有 - 只需使用普通的无效* 。每C11 6.3.2.3.1,一个指针空隙可被转换成或从一个指针到任何对象类型,一个指针到任何对象类型可被转换成一个指针无效,然后再返回;结果应比较等于原始指针。指针变量,包括一个指向另一个指针,是一个对象。 无效** 不是一个指向无效。您可以自由安全地转换,并从无效* ,但你不能保证能够安全地转换,并从无效**

You don't need to (and probably shouldn't) use a void ** at all - just use a regular void *. Per C11 6.3.2.3.1, "a pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer." A pointer variable, including a pointer to another pointer, is an object. void ** is not "a pointer to void". You can convert freely and safely to and from void *, but you're not guaranteed to be able to convert safely to and from void **.

所以,你可以这样做:

void foo (void* values, int datatype) {
    if ( datatype == 1 ) {
        int ** pnvalues = values;
        *pnvalues = malloc(5 * sizeof int);

    /*  Rest of function  */
}

等等,然后调用它类似于:

and so on, and then call it similar to:

int * new_int_array;
foo(&new_int_array, 1);

&放大器; new_int_array 的类型 INT ** ,这将让隐式转换为无效* 按富()富()将其转换回键入 INT ** 并取消对它的引用间接修改 new_int_array 来指向它动态分配新的内存。

&new_int_array is of type int **, which will get implicitly converted to void * by foo(), and foo() will convert it back to type int ** and dereference it to indirectly modify new_int_array to point to the new memory it has dynamically allocated.

有关一个指向字符串动态数组:

For a pointer to an dynamic array of strings:

void foo (void* values, int datatype) {

    /*  Deal with previous datatypes  */

    } else if ( datatype == 3 ) {
        char *** psvalues = values;
        *psvalues = malloc(5 * sizeof char *);
        *psvalues[0] = malloc(5);

    /*  Rest of function  */
}

等,并将其命名为:

and so on, and call it:

char ** new_string_array;
foo(&new_string_array, 3);

同样,&放大器; new_string_array 的类型字符*** ,再次被隐式转换为无效* 富()将其转换回和间接品牌 new_string_array 点到的存储器中的新分配的块。

Similarly, &new_string_array is type char ***, again gets implicitly converted to void *, and foo() converts it back and indirectly makes new_string_array point to the newly allocated blocks of memory.

这篇关于用C编写一个通用的功能,如何处理字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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