目前正在学习C与第2版K& R书。我对这个例子以及我的行变量的值如何被改变为getlines
函数的字符串感到困惑。
int main()
{
char line[MAXLINE];
int found = 0;
while (getlines(line, MAXLINE))
printf("Test: %s\n", line);
}
int getlines(char s[], int lim)
{
int c, i;
i = 0;
while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
程序输出"测试:[来自getlines的字符串]"。如果我从未分配过" char line"来自getlines
的返回值以及getlines
返回int
的事实," line"的值如何?得到我输入到变量" s"?
答案 0 :(得分:1)
在C函数调用中,所有参数都按值传递,因此该函数具有它们的副本。因此,函数永远不可能改变参数。听起来与你在这里观察到的相矛盾,但事实并非如此:
C中的数组有些特殊。数组标识符几乎在任何地方都被计算到数组的第一个元素(也就是:指针)的地址(例外包括sizeof
运算符)。 分配数组是不可能的,传递数组(作为函数参数或返回值)是不可能的。
同样,这看起来很矛盾,但是还有另一个函数声明规则:如果函数声明包含数组类型,则会自动调整到相应的指针类型。所以你的功能
int getlines(char s[], int lim);
实际上是以下功能:*)
int getlines(char *s, int lim);
调整函数声明中的类型并将数组的标识符作为指针一起评估的效果通常表示为数组衰减作为指针。真正传递给你的函数的是一个指针,而不是一个数组。索引该指针,函数中的代码访问原始数组。指针当然是按值传递 ,你的函数不会改变这个指针,但它可以改变指向的指针。
*)样式说明:我更喜欢总是使用指针类型编写函数声明,因为这是编译器所看到的,所以它避免了混淆。当然,有些人认为编写数组类型是好的,因为它记录了 intent ,该函数应该传递一个指向数组的指针。
答案 1 :(得分:0)
如果我从未分配过" char line"来自getlines的返回值
更正,您永远不会将getlines
的返回值分配给变量line
。
" line"的价值如何?得到我输入的字符串 变量" s"
执行getlines(line, MAXLINE)
时,变量line
虽然声明为数组" decays"传递时指向数组的第一个元素的指针。然后,在getlines
执行s[i++] = c;
时,您实际上正在写入传递给getlines
的地址(或远离该地址的一些跳数)。请记住,对数组s[i++]
建立索引会导致i
跳过隐式取消引用,远离s
中包含的地址。然后,当您在line
函数中打印main
时,您会发现某些信息已放入数组中。