这个函数如何在不使用任何指针的情况下工作?
How does this function work without using any pointers?
我正在尝试学习 C 语言并阅读 K&R 书籍。许多在线示例似乎都使用指向 return 函数值的指针。我会认为同样会用于此 K & R 函数:
/*
Reverse a string in place
*/
void reverse(char s[])
{
int c, i, j;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
int main()
{
char s[] = "HELLO";
reverse(s);
printf("%s", s);
return (0);
}
我认为在这种情况下字符串不会被反转。然而,它按照作者最初的意图向后打印 char 数组。
它是怎么做到的?我还不完全理解指针,但我认为它会像 reverse(&s)
然后 void reverse(char *s[]) {...}
由于在任何地方都没有复制字符串,因此原始字符串 必须 通过 reverse
中的数组赋值进行修改。将 void reverse(char s[])
更改为 void reverse(char *s)
不会有任何改变。未知大小的数组的行为就像指向数组第一个元素的指针。
数组在作为参数传递给函数时会衰减为指向其第一个元素的指针。因此,当您将任何类型的数组(包括字符串)传递给函数时,您实际上是通过引用传递它,函数调用后对数组所做的任何修改也将反映在调用代码中。
检查此代码的输出以丰富您对指针和数组的理解:
#include <stdio.h>
#include <stdlib.h>
void foo(int *arg, size_t len)
{
size_t i;
printf("sizeof arg is %zu\n", sizeof arg);
for(i = 0; i < len; i++)
{
printf("arg[%zu] = %d\n", i, arg[i]);
}
printf("arg's address is %p\n", (void *) arg);
}
int main()
{
int array[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
printf("sizeof array is %zu\n", sizeof array);
printf("array begins at %p in memory\n", (void *) array);
foo(array, 10);
return 0;
}
当作为参数传递给函数时,数组将隐式转换为指向数组第一个元素的指针。
这就是为什么原始数组的元素被修改而不是它的副本的原因,因为没有创建数组的副本;只有第一个元素的地址。
我也从 K&R 学了 C,这是最好的书之一,虽然读完之后,得到一本涵盖 C99 和 C11 的书。
如果你看看书中的第 5.3 节
5.3 Pointers and Arrays
他们写道:
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
所以尽管数组和指针不同,当你将数组传递给函数时,它传递的不是数组,而是指向第一个元素的指针。
一些差异:
There is one difference between an array name and a pointer that must
be kept in mind. A pointer is a variable, so pa=a and pa++ are legal.
But an array name is not a variable; constructions like a=pa and a++
are illegal.
阅读 K&R 书时要记住的一件事。他们提到过一次,50 页后他们使用它,除非你记得它,否则它看起来就像是凭空冒出来的。他们在书中没有太多重复。
我正在尝试学习 C 语言并阅读 K&R 书籍。许多在线示例似乎都使用指向 return 函数值的指针。我会认为同样会用于此 K & R 函数:
/*
Reverse a string in place
*/
void reverse(char s[])
{
int c, i, j;
for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
int main()
{
char s[] = "HELLO";
reverse(s);
printf("%s", s);
return (0);
}
我认为在这种情况下字符串不会被反转。然而,它按照作者最初的意图向后打印 char 数组。
它是怎么做到的?我还不完全理解指针,但我认为它会像 reverse(&s)
然后 void reverse(char *s[]) {...}
由于在任何地方都没有复制字符串,因此原始字符串 必须 通过 reverse
中的数组赋值进行修改。将 void reverse(char s[])
更改为 void reverse(char *s)
不会有任何改变。未知大小的数组的行为就像指向数组第一个元素的指针。
数组在作为参数传递给函数时会衰减为指向其第一个元素的指针。因此,当您将任何类型的数组(包括字符串)传递给函数时,您实际上是通过引用传递它,函数调用后对数组所做的任何修改也将反映在调用代码中。
检查此代码的输出以丰富您对指针和数组的理解:
#include <stdio.h>
#include <stdlib.h>
void foo(int *arg, size_t len)
{
size_t i;
printf("sizeof arg is %zu\n", sizeof arg);
for(i = 0; i < len; i++)
{
printf("arg[%zu] = %d\n", i, arg[i]);
}
printf("arg's address is %p\n", (void *) arg);
}
int main()
{
int array[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
printf("sizeof array is %zu\n", sizeof array);
printf("array begins at %p in memory\n", (void *) array);
foo(array, 10);
return 0;
}
当作为参数传递给函数时,数组将隐式转换为指向数组第一个元素的指针。
这就是为什么原始数组的元素被修改而不是它的副本的原因,因为没有创建数组的副本;只有第一个元素的地址。
我也从 K&R 学了 C,这是最好的书之一,虽然读完之后,得到一本涵盖 C99 和 C11 的书。
如果你看看书中的第 5.3 节
5.3 Pointers and Arrays
他们写道:
When an array name is passed to a function, what is passed is the location of the initial element. Within the called function, this argument is a local variable, and so an array name parameter is a pointer, that is, a variable containing an address.
所以尽管数组和指针不同,当你将数组传递给函数时,它传递的不是数组,而是指向第一个元素的指针。
一些差异:
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.
阅读 K&R 书时要记住的一件事。他们提到过一次,50 页后他们使用它,除非你记得它,否则它看起来就像是凭空冒出来的。他们在书中没有太多重复。