当前位置: 首页 > 知识库问答 >
问题:

如何知道char*库函数arg何时需要它可以修改的数组,而不是char指针?

司马越
2023-03-14

我是C编程新手。我知道char*char[]数组是不同的。然而,当涉及函数参数时,可以将char[]减为char*。所以函数声明可能是相同的。

但是,通过查看签名(声明),我如何知道函数是否特别需要char数组,而不是char*

例如,如果我使用的是库头文件,而函数在下面。我怎么知道要传递哪个?

// somelib.h
void foo(char *bar);

因为如果函数正在修改参数,并且如果我传递一个char*,它将得到一个segfault。这是C的,但C也一样吗?

共有3个答案

甘永春
2023-03-14

当用作函数参数时,char*xchar x[]完全等效。在许多其他情况下,情况并非如此。

对于描述为char*x(或char x[])的参数,函数不可能知道调用方实际传递了什么。调用方可能传递了一个数组(作为指向该数组第一个元素的指针传递)。它可能已经通过

该函数所能做的就是做出一个假设,并继续执行该假设。它可能会假设它传递了单个char的地址,并且只修改该char。或者,它可能会假设它已被传递了一个由1000个char组成的数组,并修改所有这些字符。该函数可能会假设(就像标准C字符串函数在很多情况下所做的那样)调用者已传递了一个nul结尾的数组(一个数组,可以有任何长度,但结尾由数值为零的哨兵char标记)。该函数可能会使用另一个参数来指定数组的长度(因此依赖于调用者传递有效数组和正确长度的假设)。

无论做出什么样的假设,如果调用方传递与函数假设不同的内容,函数都可能有未定义的行为(例如,访问或覆盖不存在的字符)。

调用者(或试图编写代码来调用函数的程序员)的情况也是如此。只有两种方法可以知道什么可以安全地传递给函数。

  1. 阅读函数的文档,并传递与文档内容一致的内容。这样做的风险(即使代码中没有bug)是程序员和代码维护人员在保持函数文档与函数实际功能的一致性方面出了名的糟糕——文档可能会说一件事,但函数实际上会做其他事情

一些样式指南鼓励函数的作者对被视为单个char地址的参数使用char*x,对需要数组的函数使用char x[]。对于编译器来说,这没有什么区别。很多程序员不遵守这样的指导方针。

习洲
2023-03-14

作为函数参数

我知道char*char[]数组不同

虽然char*char[]是不同的类型,但它们作为函数参数并没有什么不同,因为声明为数组的所有函数参数都被调整为指向此类数组元素的指针。因此,编译器将char[]函数参数调整为char*。此调整仅适用于函数参数,不适用于其他上下文。

但是,通过查看签名(声明),我如何知道函数是否特别需要char数组而不是char*?

期望char数组的函数是期望char*的函数。我想你的意思是询问如何知道函数是否期望/要求char*将指向数组的一个元素。此外,也许数组是否需要以null结尾,或者具有最小大小。

答案是光看签名是无法知道的。

我怎么知道该通过哪一个呢?

通过阅读描述函数功能的文档。如果没有文档,请阅读函数的实现。如果也没有实现,那么可以尝试对二进制文件进行反向工程。如果你不知道这个函数是做什么的,那么你不应该调用它。

因为如果函数正在修改bar参数,如果我传递一个char*,它将得到一个segfault。

我想你的意思是函数修改了指向的字符或字符。在这种情况下修改指针本身应该没问题。

如果其元素由char*指向的数组是可修改的,那么将其传递给修改数组的函数不应导致segfault。如果数组是常量,则不应将其传递给修改数组的函数。

陶富
2023-03-14

如果函数修改数组,则应声明参数char*。如果它不修改数组,则应声明参数const char*

当参数声明为const char*时,可以安全地传递字符串文本。否则,您应该向动态分配的内存传递一个数组或指针,该内存使用malloc()(在C中)或new(在C中)。

在C语言中,如果试图在没有const修饰符的情况下将文本传递给参数,就会出现编译错误,因为字符串文本是const。但由于历史原因,C中的字符串文本类型是非常量的,即使修改它们会导致未定义的行为,因此不会出现错误(但某些编译器会产生警告)。

 类似资料:
  • 我是C编程新手。我知道和数组是不同的。然而,当涉及函数参数时,可以将减为。所以函数声明可能是相同的。 但是如何通过查看签名(声明)来知道函数是否特别期望数组与? 例如,如果我使用的是库头文件,函数如下所示。我怎么知道该通过哪一个呢? 因为如果函数正在修改参数,并且如果我传递一个,它将得到一个segfault。这是C的,但C也一样吗?

  • C 17(expr.add/4)表示: 当将具有整型的表达式加到指针或从指针中减去时,结果为指针操作数的类型。如果表达式P指向具有n个元素的数组对象x的元素x[i],如果为0,则表达式P J和J P(其中J的值为J)指向(可能是假设的)元素x[i J]≤i j(i j)≤n否则,行为是未定义的。同样,表达式P-J指向(可能是假设的)元素x[i−j] 如果为0≤我−j≤n否则,行为是未定义的。 线标

  • 我试图理解map和flatMap是如何工作的,但是在下面的代码中被卡住了。flatMap()函数返回一个RDD[Char],但我希望返回的是RDD[String]。有人能解释为什么它会产生RDD[Char]吗?

  • 我正在通过反射动态实例化一个对象,方法是将字段名称与地图中类似的命名键进行匹配。其中一个字段是字符数组(char[]): 在plinko迭代器中,我为目标类上的类型编写了代码,例如。 例如,其中将是 如果field dClass类型是char[],要测试的表达式是什么?

  • a)字符指针数组:char*argv[] b)字符指针数组:char*str[] c)二维字符数组:char strarr[][7] B)*++foo指向foo下一个元素的第一个字符 C)**++foo给出foo的下一个元素的第一个字符 D)++*foo指向foo元素中的下一个字符 但我不明白为什么不允许**++str、*++str或++str的操作,而允许**++argv*++argv或++ar

  • 我想做一个Hangman游戏,这样我就可以学习JavaScript,我不知道如何改变我在JS中做的char的innerHTML。所以当我知道字符串中是否包含猜测时,我想把表示正确猜测的行转换成一个字符,使它成为一个字符,但当我运行代码时,它把最后一行转换成正确猜测,当有新的猜测时,使它消失,并把行转换成第二个正确猜测。并且没有重新识别“o”(字符串中的最后一个字符),如果我犯了语法错误,我想道歉。