这是一个关于 C 的一般性问题。(我没有很多用 C 编码的经验)所以,如果我有一个以 achar*
作为参数的函数。如何知道它是指向单个char
还是char
数组的指针,因为如果它是一个char
数组,我可以期待 a\0
但如果它不是一个 char 数组,那么我不想搜索\0
.
3 回答
在参数中是
char*
指向单个char
或char
数组的指针吗?
是的。
类型参数char*
始终是指向char
对象的指针(或空指针,不指向任何东西,如果调用者作为相应参数传递的内容)。
它不是指向数组的指针(例如,类型指针char(*)[42]
),但访问数组元素的常用方法是通过指向元素类型的指针,而不是指向整个数组。为什么?因为实际的指向数组的指针必须始终指定数组的长度(42
在我的示例中),这是不灵活的,并且不允许同一个函数处理不同长度的数组。
char*
参数可以被视为指向单个对象的指针。char
例如,一个获取输入字符的函数可以这样声明:
bool get_next_char(char *c);
这里的想法是函数的结果告诉你它是否成功;实际输入字符通过指针“返回”。(这是一个人为的例子;<stdio.h>
已经有几个从输入中读取字符的函数,它们不使用这种机制。)
比较strlen
计算字符串长度的函数:
size_t strlen(const char *s);
s
指向数组的第一个元素char
;在内部,strlen
使用该指针遍历数组,寻找终止'\0'
字符。
忽略,这两个函数const
的参数之间没有真正的区别。char*
事实上,C 没有很好的方法来区分这些情况:一个简单地指向单个对象的指针与一个指向数组第一个元素的指针。
它确实有一个不好的方法来区分。例如,strlen
可以声明为:
size_t strlen(const char s[]);
但是 C 根本没有数组类型的参数。参数声明const char s[]
“调整”为const char *s
; 它的意思完全一样。你甚至可以为看起来像数组参数的东西声明一个长度:
void foo(char s[42]);
它会被悄悄地忽略;以上实际上与以下内容完全相同:
void foo(char *s);
可能具有一些文档价值,但注释具有相同的价值——就编译器而言,[42]
具有相同的意义。
指向单个对象的指针和指向数组第一个元素的指针之间的任何区别都必须由程序员进行,最好在函数的文档中进行。
此外,这种机制不会让函数知道数组有多长。特别是对于char*
指针,通常使用空字符'\0'
作为字符串结尾的标记——这意味着调用者有责任确保该标记确实存在。否则,您可以将长度作为单独的参数传递,可能是 type size_t
。或者您可以使用您喜欢的任何其他机制,只要一切都始终如一地完成。
...因为如果它是一个
char
数组,我可以期待一个\0
...
不,你不能,至少不一定。Achar*
可以很容易地指向不以字符结尾char
的数组的第一个元素(即不包含字符串)。如果你愿意,你可以提出这样的要求。对字符串进行操作的标准库函数强加了这个要求——但他们没有强制执行它。例如,如果将指向未终止数组的指针传递给,则行为未定义。'\0'
strlen
推荐阅读: comp.lang.c FAQ的第 6 节。
您无法确定指针引用了多少字节。您需要自己跟踪这一点。
char 数组可能没有以 a 结尾,\0
在这种情况下,您需要知道数组的长度。此外,数组的长度可能为 1,在这种情况下,您有一个没有终止的字符\0
。
好处C
是您可以定义有关数据结构的详细信息,因此您不仅限于始终以 . 结尾的 char 数组\0
。
用于描述 C 数据结构的一些术语是同义词。例如,数组是数据元素的连续序列,字符数组是字符串,字符串可以以空字符 ( \0
) 结尾。