理解C中的函数和指针

时间:2010-01-23 23:49:27

标签: c

这是一个非常简单的问题,但以下函数原型是什么意思?

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)的东西时,我不能 - 在我的生活中 - 理解第二个参数的真正含义。在某种程度上,我理解它意味着“传递一个指针”,但我不太了解它自己操纵它。

11 个答案:

答案 0 :(得分:10)

关于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!
}

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:2)

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

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

int x = 42;

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

的地址

int * ptr =& x;

现在我可以将ptr传递给期望参数的int *的函数,我可以通过解除引用来使用ptr:

cout<< * ptr + 1;

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

来执行函数

答案 3 :(得分:2)

答案 4 :(得分:2)

在回复您的上一条评论时,我会尝试解释。

您知道变量包含,变量的类型会告诉您它可以容纳哪种值。因此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本身”。

答案 5 :(得分:1)

size_t *x表示您正在将指针传递给size_t'实例'。

您希望传递指针有几个原因。

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

答案 6 :(得分:0)

如果这是一个函数的参数,还有另一种解释。

当你在函数的参数中使用指针(某些东西*)并传递一个你没有传递值的变量时,你会将一个引用(一个“指针”)传递给一个值。对函数内部变量所做的任何更改都是对它引用的变量进行的,即函数外部的变量。

你仍然必须传递正确的类型 - 有两种方法可以做到这一点;要么在调用例程中使用指针,要么使用& (地址)运营商。

我刚刚写完这篇文章来证明:

#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一样。

答案 7 :(得分:0)

int square( int y, size_t* x );

声明一个函数 接受两个参数 - 一个整数,一个指向unsigned(可能是大)整数的指针,以及返回一个整数。

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

*(星号)在声明(和强制转换)或取消引用int* ptr;使ptr成为指向整数的指针)在lvalue or rvalue使用时指针> *ptr = 10;将{10}分配给ptr所指向的内存。幸运的是,相同的符号用于乘法(例如,Pascal使用^作为指针)。

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

定义函数时,参数现在命名 local 变量,其值由调用者分配。

在传递对象by reference输出参数时使用指针函数参数,其中传入指向函数存储输出值的位置的指针。

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

答案 8 :(得分:0)

你说你知道int sq(int x, int y)是什么。这意味着我们将两个变量x,y作为函数传递给sq.Say 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

因此,如果要修改原始值,请使用指针。 如果要使用这些值,则无需使用指针。

答案 9 :(得分:0)

上面的大部分解释都得到了很好的解释。我想添加这种论证传递的应用观点。

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

例如:愚蠢但给你一个场景

//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)传递一个对象(一个类'对象或一个结构等)是一个代价高昂的过程(即如果大小太大,那么内存和其他约束等)

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

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

答案 10 :(得分:0)

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的指针,我们 使用&运算符 - &u。这意味着“u的地址”,是一个 指针。

因为uint&u是指向int(或int *)的指针,这是sq_B()的参数2指定的类型}。

有问题吗?