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;
}
上面的代码打印所有字符串。
我的问题是:
在
printAllStrings
函数中传递的 parameter(char** arr[]
) 字符串数组,我们可以在指针 - 上传递指针吗char** arr
?这一行是什么意思
char** ptr=(char**)*arr
;我了解这种指向 char 类型的指针转换。但是为什么必须强制转换的指针已经指向 char 类型?
解决方案
- 在 printAllStrings 函数中传递参数
(char** arr[])
的字符串数组,我们可以在指针 - 上传递指针吗char** arr[]
?
在你上面的例子中,你有char** arr[]
和char** arr[]
(两者是一样的)所以你的“我们可以通过吗?” 问题不清楚。如果您询问是否可以将参数更改为(char ***arr)
,那么可以,因为第一级间接(例如[ ]
)被转换为指针。
- 这一行是什么意思
char** ptr=(char**)*arr
;我了解这种指向 char 类型的指针转换。但是为什么必须强制转换的指针已经指向 char 类型?
原因是您的参数是const char** arr[]
,然后您声明char** ptr
which丢弃const
限定符on 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
then 是有意义的,如果你尝试做一些你不允许做的事情,比如更改字符串文字,编译器会发出警告,例如,如果你尝试:
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
如果您还有其他问题,请仔细查看并告诉我。我不确定这是否是您想要的,但根据您的代码和问题,这似乎是最合乎逻辑的选择。
推荐阅读
- android - 如何在类适配器中传递图像视图参数,Kotlin
- bootstrap-4 - Bootstrap 4 可过滤选择(下拉菜单)
- mysql - SQL SELF 和 INNER JOINS 在一个查询中
- reactjs - Typescript + React 测试库 - 'SidebarItem' 指的是一个值,但在这里被用作一种类型。您的意思是“typeof SidebarItem”吗?ts(2749)
- weblogic - 通过腻子中的脚本创建Weblogic域错误
- python-3.x - Python:给定 2 个二进制字符串 s 和 t,打印将 s 转换为 t 的最小相邻交换数
- audio - 如何同时分析 MP3 的节拍/鼓时间戳、触发动作和播放 (Rust)
- vue.js - Vue Router 在开发中工作正常,但与生产中的路由不匹配
- javascript - 扁平化一些嵌套数据时遇到问题
- javascript - 将 join() 添加到 map() 函数