【问题标题】:Understanding functions and pointers in C理解 C 中的函数和指针
【发布时间】:2011-01-08 16:14:09
【问题描述】:

这是一个很简单的问题,但是下面的函数原型是什么意思呢?

int square(int y, size_t* x)

size_t* 是什么意思?我知道 size_t 是一种数据类型(int >=0)。但是我如何阅读附在它上面的 * 呢?它是指向 x 的内存位置的指针吗?总的来说,我在使用这些东西时遇到了麻烦,如果有人可以提供方便的参考,我将不胜感激。


谢谢大家。我了解指针是什么,但我想我很难理解指针和函数之间的关系。当我看到定义为int sq(int x, int y) 的函数原型时,我就非常清楚发生了什么。然而,当我看到int sq( int x, int* y) 之类的东西时,我无法理解第二个参数的真正含义。在某种程度上,我理解它的意思是“传递指针”,但我对事情的理解还不够好,无法自己操纵它。

【问题讨论】:

    标签: c


    【解决方案1】:

    understanding pointers 的教程怎么样?

    然而,在这种情况下,指针可能用于修改/返回值。在 C 中,函数可以返回值有两种基本机制(请原谅这个愚蠢的例子):

    可以直接返回值:

    float square_root( float x )
    {
        if ( x >= 0 )
            return sqrt( x );
        return 0;
    }
    

    或者可以通过指针返回:

    int square_root( float x, float* result )
    {
        if ( x >= 0 )
        {
            *result = sqrt( result );
            return 1;
        }
        return 0;
    }
    

    第一个叫:

    float a = square_root( 12.0 );
    

    ... 而后者:

    float b;
    square_root( 12.00, &b );
    

    请注意,后一个示例还允许您检查返回的值是否真实——这种机制在 C 库中广泛使用,其中函数的返回值通常表示成功(或没有成功),而值本身是通过参数返回的。

    因此你可以写后者:

    float sqresult;
    if ( !square_root( myvar, &sqresult ) )
    {
       // signal error
    }  
    else
    { 
       // value is good, continue using sqresult!
    }
    

    【讨论】:

      【解决方案2】:

      *x 表示 x 是指向 size_t 类型内存位置的指针。

      您可以使用 x = &y; 设置位置 或将值设置为 x 点:*x = 0;

      如果您需要更多信息,请查看:Pointers

      【讨论】:

        【解决方案3】:

        原型意味着该函数接受一个整数 arg 和一个 arg,它是指向 size_t 类型的指针。 size_t 是在头文件中定义的类型,通常是 unsigned int,但不只是使用“unsigned int* x”的原因是为了让编译器编写者可以灵活地使用其他东西。

        指针是一个保存内存地址的值。如果我写

        int x = 42;

        然后编译器将在内存中分配 4 个字节,并在我使用 x 时记住位置。如果我想显式传递该位置,我可以创建一个指针并将 x 的地址分配给它:

        int* ptr = &x;

        现在我可以将 ptr 传递给需要 int* 作为参数的函数,并且可以通过取消引用来使用 ptr:

        cout

        将打印出 43。 您可能想要使用指针而不是值的原因有很多。 1) 在传递给函数时避免复制构造结构和类 2) 您可以拥有多个变量句柄 3) 这是在堆上操作变量的唯一方法 4) 您可以使用它们来传递结果通过写入 arg 指向的位置来退出函数

        【讨论】:

        • 附带说明,我一直认为原因 (4) 是在基于 C 的语言中不幸地(但有时是不可避免地)使用指针。
        • cout
        【解决方案4】:
        【解决方案5】:

        作为对您上一条评论的回应,我会尽力解释。

        你知道变量持有一个,变量的类型告诉你它可以持有什么样的值。所以int 类型变量可以保存一个在一定范围内的整数。如果我声明如下函数:

        int sq(int x);
        

        ...那么这意味着sq 函数需要您提供一个整数值,它会返回一个整数值。

        如果变量声明为指针类型,则意味着该变量本身的值是“另一个变量的位置”。因此,int * 类型变量可以作为其值保存,“另一个变量的位置,并且该其他变量具有 int 类型”。然后我们可以将其扩展到函数:

        int sqp(int * x);
        

        这意味着sqp 函数需要您提供一个值,该值本身就是int 类型变量的位置。这意味着我可以这样称呼它:

        int p;
        int q;
        
        p = sqp(&q);
        

        &q 只是表示“给我q位置,而不是它的值”)。在sqp 中,我可以像这样使用该指针:

        int sqp(int * x)
        {
            *x = 10;
            return 20;
        }
        

        *x 的意思是“作用于变量x 给出的位置,而不是x 本身”)。

        【讨论】:

        • 有人正在向您发送与此答案相关的question 回复:)。
        【解决方案6】:

        size_t *x 表示您正在传递一个指向 size_t 'instance' 的指针。

        您想要传递指针有几个原因。

        1. 这样函数就可以修改调用者的变量。 C 使用按值传递,因此修改函数内部的参数不会修改原始变量。
        2. 出于性能原因。如果参数是结构,则按值传递意味着您必须复制该结构。如果结构足够大,这可能会导致性能下降。

        【讨论】:

          【解决方案7】:

          考虑到这是函数的参数,还有进一步的解释。

          当你在函数的参数中使用指针(something*)并且你传递一个变量时,你不是在传递一个值,你是在传递一个对值的引用(一个“指针”)。对函数内部的变量所做的任何更改都是针对它所引用的变量进行的,即函数外部的变量。

          您仍然必须传递正确的类型 - 有两种方法可以做到这一点;在调用例程中使用指针或使用 & (addressof) 运算符。

          我只是快速写了这个来演示一下:

          #include <stdio.h>
          
          void add(int one, int* two)
          {
              *two += one;
          }
          
          int main()
          {
              int x = 5;
              int y = 7;
              add(x,&y);
          
              printf("%d %d\n", x, y);
          
              return 0;
          }
          

          这就是 scanf 之类的工作方式。

          【讨论】:

          • 这仍然是按值传递,因为您传递的是指向函数的指针的副本,而不是引用。
          • 谢谢大家。我了解指针是什么,但我想我很难理解指针和函数之间的关系。当我看到定义为 int sq(int x, int y) 的函数原型时,我就非常清楚发生了什么。然而,当我看到类似 int sq( int x, int* y) 的东西时,我无法理解第二个参数的真正含义。在某种程度上,我理解它的意思是“传递一个指针”,但我对事情的理解还不够好,无法自己操纵它。
          【解决方案8】:
          int square( int y, size_t* x );

          声明一个函数,它接受两个参数 - 一个整数,一个指向无符号(可能很大)整数的指针,以及返回一个整数。

          size_t 是无符号整数类型(通常是typedefreturned by sizeof() operator

          *(星号)在声明(和强制转换)中使用时表示指针类型(例如,int* ptr; 使 ptr 成为指向整数的指针),或在使用时取消引用指针在lvalue or rvalue*ptr = 10; 将十分配给ptr 指向的内存)。我们很幸运,乘法使用了相同的符号(例如,Pascal 使用 ^ 表示指针)。

          在函数声明时,参数的名称(xy 这里)并不重要。您可以在 .c 文件中使用不同的参数名称定义您的函数。函数的调用者只对函数参数的类型和数量以及返回类型感兴趣。

          当您定义函数时,参数现在命名为 本地 变量,其值由调用者分配。

          指针函数参数用于传递对象by reference 或作为输出参数,您可以在其中传递指向函数存储输出值的位置的指针。

          C 是美丽而简单的语言 :)

          【讨论】:

            【解决方案9】:

            你说你知道int sq(int x, int y)是什么。这意味着我们将两个变量x,y作为参数传递给函数sq。说sq函数是从main()函数调用的

            main()
            {
                /*some code*/
                x=sr(a,b);
                /*some other code*/
            }
            int sq(int x,int y)
            {
                /*code*/
            }
            

            在 sq 函数中对 x,y 进行的任何操作都不会影响 a,b 的值 而在

            main()
            {
                /*some code*/
                x=sq(a,&b);
                /*some other code*/
            }
            int sq(int x,int* y)
            {
                /*code*/
            }
            

            对y做的操作会修改b的值,因为我们指的是b

            所以,如果要修改原始值,请使用指针。 如果您想使用这些值,则无需使用指针。

            【讨论】:

              【解决方案10】:

              上面的大部分解释都得到了很好的解释。我想补充一下这种参数传递的应用观点。

              1) 当一个函数必须返回多个值时,它不能通过使用多个返回类型来完成(微不足道,我们都知道)。为了实现将指向函数的指针作为参数传递将提供一种在调用函数(例如:main)中反映被调用函数(例如:sqrt)内部所做更改的方法

              例如:傻但给你一个场景

              //a function is used to get two random numbers into x,y in the main function
              int main()
              {    
              int x,y;    
              generate_rand(&x,&y);    
              //now x,y contain random values generated by the function
              }
              
              void generate_rand(int *x,int *y)
              {
              *x=rand()%100;
              *y=rand()%100;
              }
              

              2)当传递一个对象(一个类的对象或结构等)是一个代价高昂的过程(即如果大小太大,那么内存n其他约束等)

              例如:不是将结构作为参数传递给函数,而是指针可以很方便,因为指针可用于访问结构,但也可以节省内存,因为您没有将结构存储在临时位置(或堆栈)

              只是几个例子..希望对您有所帮助..

              【讨论】:

                【解决方案11】:

                2 年过去了,仍然没有答案被接受?好吧,我试着解释一下……

                让我们来看看你在问题中提到的两个函数:

                int sq_A(int x, int y)

                你知道 - 这是一个名为 sq_A 的函数,它接受两个 int 参数。很简单。

                int sq_B(int x, int* y)

                这是一个名为sq_B 的函数,它接受两个参数:

                • 参数1是int

                • 参数 2 是一个指针。这是一个指向int的指针

                所以,当我们调用sq_B()时,我们需要传递一个指针作为第二个 范围。不过,我们不能只传递任何指针 - 它必须是指向 int 类型的指针。

                例如:

                int sq_B(int x, int* y) {
                    /* do something with x and y and return a value */
                }
                
                int main() {
                    int t = 6;
                    int u = 24;
                    int result;
                
                    result = sq_B(t, &u);
                
                    return 0;
                }
                

                main() 中,变量uint。为了获得指向u 的指针,我们 使用 &amp; 运算符 - &amp;u。这意味着“u 的地址”,并且是 指针。

                因为uint,所以&amp;u是一个指向int(或int *)的指针,这是sq_B()的参数2指定的类型。

                有什么问题吗?

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-02-12
                  • 1970-01-01
                  • 2013-06-28
                  • 1970-01-01
                  • 2015-02-19
                  相关资源
                  最近更新 更多