按指针调用和按值 C 调用

call by pointers and call by value C

提问人:Iuliana 提问时间:4/1/2018 最后编辑:Iuliana 更新时间:4/2/2018 访问量:102

问:

如何编写这个C程序通过指针和按值传递?我创建了这个程序,它从 to 生成一个数组,主对角线从下到上读取,但我不知道如何创建另外两个通过指针和值传递的程序 我只能通过这两种方法编写另外两个具有相同输入和输出的程序。我是 C 语言的初学者,我不知道如何做到这一点。10x10-100100

#include <stdio.h>
#include <stdlib.h>

#define N 10
#define M 10

int my_rand(int max, int min)
{
    return (min + rand() / (RAND_MAX / (max - min + 1) + 1));
}

void generate_array(int(*array)[M])
{
    printf("Table:");
    for (int i = 0; i < N; i++)
    {
        printf("\n");
        for (int j = 0; j < M; j++)
        {
            array[i][j] = my_rand(-100, 100);
            printf("%4d ", array[i][j]);
        }
    }
}
void print_diagonal(int(*array)[M])
{
    printf("\n\nThe main diagonal read from bottom to top:\n");
    for (int i = N - 1; i >= 0; i--)
    {
        printf("%4d ", array[i][i]);
    }
}

int *create_array(int(*array)[M])
{
    static int new_array[M] = { 0 };
    for (int i = 0; i < N; i++)
        new_array[i] = array[i][i];
    return new_array;
}

void reverseArray(int arr[], int start, int end)
{
    int temp;
    while (start < end)
    {
        temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        start++;
        end--;
    }
}

void printArray(int arr[])
{
    int i;
    for (i = N; i < N; i++)
        printf("%4d ", arr[i]);
    printf("\n");
}

int main(void)
{
    int array1[N][M] = { 0 }, *aux_array;
    generate_array(array1);
    print_diagonal(array1);
    aux_array = create_array(array1);
    reverseArray(aux_array, 0, N - 1);
    printArray(aux_array);
}

任何帮助将不胜感激。

C 按引用 按值传递 指针传递

评论

1赞 Some programmer dude 4/1/2018
C 只有传递值。可以模拟引用传递。
2赞 Some programmer dude 4/1/2018
尝试正确格式化您的代码。缩进对我们人类理解你的代码真的很有好处。
0赞 myradio 4/2/2018
正如 John 所说,在 C 语言中,你总是通过值传递。但是,您可以区分传递值本身或指向值的指针。在你的问题中,你说你有你的代码,你需要编写另外两个版本的代码,按值和指针传递参数。首先,重要的是要注意,如果这两种方法,您必须已经在使用一种。你的问题让我觉得你不明白。然后,你必须知道,在 C 中,你总是通过传递指向其第一个元素(指针的值)的指针来传递数组。然后你会更清楚你想要什么。

答:

0赞 John Bode 4/2/2018 #1

C 仅支持按值传递。函数定义中的形式参数在内存中始终是与函数调用中的实际参数不同的对象(假设实际参数本身是一个对象,它不必是对象)。

我们可以通过传递指针(按值传递)来伪造按引用传递语义。下面是一个典型的例子:

void swap( int *a, int *b )
{
  int tmp = *a;
  *a = *b;
  *b = tmp;
}

我们接收的不是整数对象,而是指向两个整数对象的指针。我们使用一元运算符来取消引用指针并访问指向的对象。如果我们这样称呼该函数:*

int main( void )
{
  int x = 1;
  int y = 2;

  ...
  swap( &x, &y );
  ... 
  return 0;
}

根据上面的代码,当我们输入函数时,以下情况是正确的:swap

 a == &x        // int *
*a ==  x  == 1  // int

 b == &y        // int *
*b ==  y  == 2  // int

执行函数的主体后,满足以下条件:swap

 a == &x        // no change
*a ==  x  == 2

 b == &y        // no change
*b ==  y  == 1

事情变得奇怪的地方是当你将数组表达式作为函数参数传递时。C 有一个规则,即当数组表达式不是 or 一元运算符的操作数,或者不是用于初始化声明中的字符数组的字符串文本时,表达式将从数组类型转换(“衰减”)为指针类型,并且表达式的值是第一个元素的地址。sizeof&

IOW,给定代码

int arr[10];

foo( arr );

由于它不是 or 一元运算符的操作数,因此调用中的表达式会自动从类型“10-element array of ”转换为 “pointer to”,并且传递给 foo 的值是第一个元素的地址;IOW,这个调用与写作相同sizeof&arrfoointint

foo( &arr[0] );

函数定义将写成

void foo( int *a ) // or int a[], which means the same thing
{
  // do something with a[i]
}

IOW,你不能在 C 中按值传递数组。

所以,看看你的代码:

int my_rand(int max, int min)

两者都按值传递maxmin

void generate_array(int(*array)[M])

void print_diagonal(int(*array)[M])

它们接收指向 2D 数组的第一个元素的指针,因此我们伪造了按引用传递。

void reverseArray(int arr[], int start, int end)

我们接收到数组第一个元素的指针(并且都像在函数参数声明中一样解释),并且按值传递。T a[]T a[N]T *astartend

void printArray(int arr[])

同样,我们收到指向数组第一个元素的指针。