【问题标题】:Can C function parameters set variables?C函数参数可以设置变量吗?
【发布时间】:2017-05-10 19:21:24
【问题描述】:

我不知道在下面的 C 代码中是如何设置 firstname 和 lastname 变量的。

printf("Hello, %s, %s\n", firstname, lastname);

看起来 readln 函数的 char [s] 参数正在设置名字和姓氏。

这可能吗,如果可以,这叫什么,所以我可以做一些研究。

谢谢

编辑:下面是一个更简单的版本。参数好像是在设置变量。

int foo(char s[]){
    s[0]='w';
    s[1]='\0';

    return 5;
}

int main() {

    char name[2];
    int wtf;

    wtf = foo(name);
    printf("%s\n", name);
}

参数 char s[] 为设置名称


#include <stdio.h>

#define STRLEN 5


int readln(char s[], int maxlen) {
    char ch;
    int i;
    int chars_remain;
    i = 0;
    chars_remain = 1;
    while (chars_remain) {
        ch = getchar();
        if ((ch == '\n') || (ch == EOF) ) {
            chars_remain = 0;
        } else if (i < maxlen - 1) {
            s[i] = ch;
            i++;
        }
    }
    s[i] = '\0';
    return i;
} 

int main(int argc, char **argv) {
    char firstname[STRLEN];
    char lastname[STRLEN];
    int len_firstname;
    int len_lastname;
    printf("Enter your first name:");
    len_firstname = readln(firstname, STRLEN);
    printf("Enter your last name:");
    len_lastname = readln(lastname, STRLEN);
    printf("Hello, %s, %s\n", firstname, lastname);
    printf("Length of firstname = %d, lastname = %d", len_firstname, len_lastname);
}

【问题讨论】:

  • 通过引用传递?

标签: c function parameters


【解决方案1】:

当您将数组作为参数传递给函数时,它与传递数组地址完全一样。然后,函数可以修改这个地址的上下文,也就是数组本身。

例如,函数可以定义为int readln(char *s, int maxlen),并且功能将保持不变。

调用函数时,您可以使用readln(firstname, STRLEN)readln(&amp;firstname[0], STRLEN)。两者都适用于任何一个函数定义(它们是正交的)。

关于这个主题的一个很好的tutorial

【讨论】:

  • 有趣。谢谢你。澄清这种愚蠢只适用于数组?
  • 是的,这种行为对于数组来说有点令人困惑。如果您传递原语或结构并且不使用&amp;,它们将按值传递,这与数组不同。
  • @seamus 回复:“仅适用于数组?”当用作函数参数(和其他情况)时,函数也会转换为指向函数的指针foo(rand)。然而接收函数foo(int (*f)()) 肯定不能通过该指针读取或写入函数rand()。它可以执行该功能。
  • @SHG "就像传递数组地址一样。" --> 差不多。 “这就像传递数组第一个元素的地址一样。”这种差异是微妙的。这两个地址的值是等价的,但类型不同,很少有位模式。
【解决方案2】:

通用术语是“按引用传递” - readln 中的形参 s 与实际参数 firstnamelastname 在同一块内存中相应的函数调用。

C实际上是通过值传递所有函数参数传值 - 函数定义中的形参是与函数调用中的实参在内存中的一个单独的对象,实参的值是被复制的到形式参数:

void swap( int a, int b ) // a receives a *copy* of x's value, b receives
{                         // a *copy* of y's value
  int t = a;              // updates to a and b have no effect on x and y
  a = b;
  b = t;
}

void bar( void )
{
   int x = 1, y = 2;
   swap( x, y );          // x and y are not actually updated
}

我们伪造通过传递指向我们要修改的对象的指针来传递引用语义:

void swap( int *a, int *b ) // a receives the *address* of x, b receives the
{                           // address of y
  int t = *a;               // updates to *a and *b *do* have and effect on
  *a = *b;                  // x and y
  *b = t;
}

void bar( void )
{
  int x = 1, y = 2;
  swap( &x, &y );          // instead of passing the *values* of x and y,
}                          // we pass their addresses.

同样,ab 是内存中与 xy 不同的对象,但它们不是接收 xy,而是接收他们的地址。爱荷华

 a == &x;
 b == &y;
*a ==  x;
*b ==  y;

数组的情况有点奇怪 - 除非它是 sizeof 或一元 &amp; 运算符的操作数(或用于在声明中初始化字符数组的字符串文字),表达式 “T 的 N 元素数组”类型的 em> 将被转换(“衰减”)为“指向 T 的指针”类型的表达式,表达式的值将是第一个元素的地址数组。

因此,如果将数组表达式传递给函数,函数实际接收的是指向数组第一个元素的指针,因此您不需要在函数调用中使用&amp; 运算符。这就是readln 发生的事情;参数s 指向函数调用中数组的第一个元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    相关资源
    最近更新 更多