c - 将参数传递给函数并进行转换

标签 c

我是 C 语言新手,在以下练习中存在一些误解:

void printAllStrings(const char** arr[])
{
    while(*arr!=NULL)
    {
        char** ptr=(char**)*arr;
        while(*ptr!=NULL)
        {
            printf("%s\n",*ptr);
            ptr++;
        }
        arr++;
    }
}

int main()
{
    char* arrP1[]={"father","mother",NULL};
    char* arrP2[]={"sister","brother","grandfather",NULL};
    char* arrP3[]={"grandmother",NULL};
    char* arrP4[]={"uncle","aunt",NULL};
    char** arrPP[]={arrP1,arrP2,arrP3,arrP4,NULL};

    printf("Before sort :\n");
    printAllStrings(arrPP);
    sort(arrPP);

    printf("\nAfter sort :\n");
    printAllStrings(arrPP);
    printf("\nMaximum length string : %s \n",maxLengthString(arrPP));

    return 0;
}    

上面的代码打印所有字符串。

我的问题是:

  1. printAllStrings函数中,传递的参数(char** arr[])字符串数组,我们可以在指针上传递指针 - char ** 到达

  2. 这一行的含义是什么char** ptr=(char**)*arr;我理解这种对 char 类型的指针的转换。 但为什么指针已经指向char类型了呢?

最佳答案

  1. In printAllStrings function the the passed parameter(char** arr[]) array of strings, could we pass pointer on pointer - char** arr[].

在上面的示例中,您有 char** arr[]char** arr[] (两者相同),因此您的“我们可以通过吗?”问题不清楚。如果您询问是否可以将参数更改为 (char ***arr) ,那么可以,因为第一级间接寻址(例如 [ ] )被转换为指针。

  1. What the meaning of this row char** ptr=(char**)*arr; I undersatnd that this casting of pointers to char type. But why the pointer have to be casted is already points to char type?

原因是您的参数是 const char** arr[] ,然后您声明 char** ptr ,这丢弃了 const 上的 arr 限定符const char **char ** 不一样。因此,当您尝试使用取消引用的 ptr 初始化 arr 时,例如( char** ptr=arr; ) 编译器提示 const 限定符被丢弃。

而不是正确解决问题,例如

const char **ptr = *arr;

你“捏造”初始化以强制丢弃 const 限定符 - 导致 ptr 不保留 const 类型,这可以防止编译器在你尝试以非常量方式使用 ptr 时发出警告(真的很糟糕)当你放弃 const 限定符时会发生)

我可能是错的——但看起来赋值的目的是让您保留用于初始化指针数组的字符串文字const 性质。因此,不要将数组声明为:

char* arrP1[]={"father","mother",NULL};

您应该将它们声明为 const 指向 char 的指针数组,例如

const char *arrP1[]={"father","mother",NULL};

您的 printAllStrings 参数就有意义了,如果您尝试执行不允许执行的操作(例如更改字符串文字),编译器会发出警告,例如如果你尝试:

arrP1[0][0] = 'l';

(编译器将抛出 error: assignment of read-only location ‘*arrP1[0] )

如果您在代码中一致地携带类型,则不必在任何地方“捏造”任何强制转换,并且编译器可以帮助保护您免受自己的伤害。例如,可以通过以下方式对类型进行简单的修改,以确保字符串文字符合 const 资格(同时仍然允许您对数组进行排序):

#include <stdio.h>
#include <string.h>

void printAllStrings (const char **arr[])
{
    while (*arr != NULL) {
        const char **ptr = *arr;
        while (*ptr != NULL) {
            printf ("%s\n", *ptr);
            ptr++;
        }
        arr++;
    }
}

const char *maxLengthString (const char **arr[])
{
    size_t max = 0;
    const char *longest = NULL;

    while (*arr != NULL) {
        const char **ptr = *arr;
        while (*ptr != NULL) {
            size_t len = strlen (*ptr);
            if (len > max) {
                max = len;
                longest = *ptr;
            }
            ptr++;
        }
        arr++;
    }
    return longest;
}

int main (void) {

    const char *arrP1[] = {"father", "mother", NULL};
    const char *arrP2[] = {"sister", "brother", "grandfather", NULL};
    const char *arrP3[] = {"grandmother", NULL};
    const char *arrP4[] = {"uncle", "aunt", NULL};
    const char **arrPP[] = {arrP1, arrP2, arrP3, arrP4, NULL};

    printf ("Before sort :\n");
    printAllStrings (arrPP);

    // sort (arrPP);  /* you didn't post sort, so the following swaps */
    const char **tmp = arrPP[0];    /* simple swap example */
    arrPP[0] = arrPP[1];
    arrPP[1] = tmp;

    printf ("\nAfter sort :\n");
    printAllStrings (arrPP);

    printf ("\nMaximum length string : %s \n", maxLengthString (arrPP));

    return 0;
}

(您没有发布 sort() ,因此上面的元素 a 简单地交换以显示您的 arrPP 保留了排序的能力,并且添加了 maxLengthString () 的快速实现以使您的最后一条语句起作用 - 但请注意,它如果多个字符串长度相同,则仅查找最长字符串中的第一个)

示例使用/输出

$ ./bin/array_ptp_const_char
Before sort :
father
mother
sister
brother
grandfather
grandmother
uncle
aunt

After sort :
sister
brother
grandfather
father
mother
grandmother
uncle
aunt

Maximum length string : grandfather

仔细检查一下,如果您还有其他问题,请告诉我。我不确定这是否是您正在寻找的,但根据您的代码和问题,这似乎是最合乎逻辑的选择。

关于c - 将参数传递给函数并进行转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50343669/

相关文章:

c - C中选择,为什么会失败?

c++ - 静态初始化不使用 _initterm 而是使用 _Init_thread_header()/footer()

c - 在 C 语言中,什么是 sscanf 的安全替代品?

python - C : What assumptions can be made about the value of the underlying variable? 中的枚举

c++ - 将 C++ 字符串操作转换为 C 的问题

c - Linux 上的汇编编译器。纳斯姆还是AS?

c - 使用 -1 作为无效值是不好的做法吗(对于枚举和可能未知的值)

c - 当我的 main.c 不使用 pthreads 时,为什么我必须在 main.c 编译中显式链接到 pthreads?

c - 当位域大于字节大小时,字节顺序如何影响位域

c - 发送到 : Resource temporarily unavailable (errno 11)