在不使用任何指针的情况下该函数如何工作?

时间:2019-01-29 18:56:15

标签: c pointers reverse

我正在尝试学习C并阅读《 K&R》一书。在线上的许多示例似乎都使用指针从函数返回值。我会认为那时将同样用于此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[]) {...}

4 个答案:

答案 0 :(得分:2)

由于在reverse中的数组赋值不能修改原始字符串 的任何地方都不能复制该字符串。将void reverse(char s[])更改为void reverse(char *s)不会有任何改变。大小未知的数组的行为就像指向该数组第一个元素的指针一样。

答案 1 :(得分:2)

数组作为函数的参数传递时,会衰减到指向其第一个元素的指针。因此,当您将任何类型的数组(包括字符串)传递给函数时,您实际上是通过引用将其传递,并且在函数调用之后,在函数内对该数组所做的任何修改也将反映在调用代码中。

检查此代码的输出,以丰富您对指针和数组的理解:

#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;
}

答案 2 :(得分:1)

我还从K&R学到了C,它是目前最好的书之一,尽管在阅读它之后,可以获得涵盖C99和C11的书。

如果您看书中的5.3节

  

5.3指针和数组

他们写道:

  

将数组名称传递给函数时,传递的是   初始元素的位置。在调用的函数中,此   参数是局部变量,因此数组名称参数是   指针,即包含地址的变量。

因此,尽管数组和指针不同,但是当您将数组传递给函数时,它不会传递数组,而是传递给第一个元素的指针。

一些区别:

  

数组名称和必须在其中的指针之间有一个区别   要牢记。指针是变量,因此pa = a和pa ++是合法的。   但是数组名称不是变量;像a = pa和a ++这样的结构   是非法的。

阅读K&R书时要牢记的一件事。他们只提到过一次,后来又使用了50页,除非您还记得,否则它看起来好像是从无到有。他们在书中重复的次数很少。

答案 3 :(得分:0)

当作为参数传递给函数时,该数组将隐式转换为指向数组第一个元素的指针。

这就是为什么修改原始数组的元素而不是对其进行复制的原因,因为没有进行数组的复制;仅第一个元素的地址。