【问题标题】:How does this function work without using any pointers? [duplicate]这个函数如何在不使用任何指针的情况下工作? [复制]
【发布时间】:2019-06-22 23:38:48
【问题描述】:

我正在尝试学习 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(&amp;s) 然后 void reverse(char *s[]) {...}

【问题讨论】:

  • 拿笔和纸。使用这些工具执行程序。一切都会变得清晰
  • In C, are arrays pointers or used as pointers? 的可能重复项 接受的答案应该会有所帮助
  • void reverse(char s[]);void reverse(char *s); 100% 完全相同
  • 参数s 是一个char *,因为在参数列表中使用了符号char s[]。这是数组下标的直接使用。由于参数不是字符串文字,它应该可以正常工作(只要您不将空字符串传递给函数)。
  • 想象int a[] = {1,2}; int c; c=a[0]; a[0] = a[1]; a[1] =c;会发生什么?

标签: c pointers reverse


【解决方案1】:

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

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

#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】:

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

【讨论】:

    【解决方案3】:

    我还从 K&R 学习了 C,它是目前最好的书之一,虽然在阅读之后,得到一本涵盖 C99 和 C11 的书。

    如果你看书中的第 5.3 节

    5.3 指针和数组

    他们写道:

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

    所以虽然数组和指针不同,但是当你将数组传递给函数时,它传递的不是数组,而是指向第一个元素的指针。

    一些区别:

    数组名和指针之间有一个区别 请牢记。指针是一个变量,所以 pa=a 和 pa++ 是合法的。 但是数组名不是变量;像 a=pa 和 a++ 这样的结构 是非法的。

    阅读 K&R 书籍时要记住一件事。他们提到过一次,50页后他们使用它,除非你记得它,否则它看起来就像是凭空出现的。他们在书中很少重复自己。

    【讨论】:

    • 谢谢你也给了你一个upvote...在第98页找到它
    【解决方案4】:

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

    这就是为什么原始数组的元素被修改而不是它的副本的原因,因为没有制作数组的副本;只有第一个元素的地址。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2022-01-14
      • 1970-01-01
      相关资源
      最近更新 更多