2009-12-13 50 views
2

我知道,指针包含的变量的地址,例如:这个C代码错了吗?

int c = 5; 
int *p; 
p = &c; 
printf("%d",*p); // Outputs 5. 

但是,如果我想的地址发送给一个函数是什么:

void function (int *p) 
{ 
    p++; 
} 
int c; 
function (&c); 

当函数被调用时的值&c被分配给int *p。我想确切的说明是:*p = &c;,但我不明白这是什么意思。

回答

4

我更喜欢写int* p = &c;,也就是说,指向int类型的指针被分配了c的地址。

指针符号可能会造成混淆,因为你已经注意到了,因为这两个是相同的:

int *p = &c; 

int *p; 
p = &c; 

希望这有助于!

编辑:混乱是因为*既用作解除引用运算符,也用于声明指针。因此,当p包含地址c时,*p将指针取消引用并返回值c。但是当你说int *p = &c;时,*说“p是指向int的指针”,但是没有进行任何解引用。

2

您确定p++;是您的意思吗?这会增加p指向的位置,但不会递增当前位置的值。如果你想增加价值(即使c变成6),那么你想要的是(*p)++;

+0

不,它不会“增加p指向的位置”,它只是增加p。 – 2009-12-13 13:07:07

+0

对不起,我的部分表达不好。由于'p'是一个指针,所以递增它会调用指针算术,这会将指针有效指向的内存地址移动一个点(改变*位置*,而不是*位置处的值* - 这就是我的意思通过递增位置,而不是递增位置处的值)。 – Amber 2009-12-13 13:10:37

3

如果你想要的功能,以增加c&c调用,那么这样写:

void function(int *p) { ++(*p); } 

function(int *p)意味着p是函数的参数。因此,无论呼叫者给出的值如何,都将分配给p(而不是*p)。

p的类型是int *。也就是说,p是一个指向int的指针。

如果p是一个指向int的指针,那么*p是它指向的int。

c是一个int。因此&c是一个指向int的指针,它指向的int是c。因此,如果p&c,则*pc

随着我的版本的功能,此代码:

int c = 5; 
function(&c); 

是否与此相同的代码:

int c = 5; // same as before 
int *p; // parameter of the function 
p = &c; // assign the caller's value to the parameter 
++(*p); // body of the function, increments *p, which is the same as c. 

这确实与此相同的代码:

int c = 5; 
++c; 
+0

非常感谢很多人,这正是我所要求的 – hamza 2009-12-15 17:30:19

3

我无法真正弄清楚你的问题,但function看起来像我的错误,你的意思是我s,或许,

++(*p) 

否则它是一个没有操作。

+0

严格地说,该函数中的'p ++'调用未定义的行为(因为递增p会创建一个指向无效位置的指针)。实际上,在所有普通的C编译器中,它什么都不做。 – 2009-12-13 14:40:10

+0

不,没有未定义的行为,因为递增的p永远不会使它脱离函数并立即被丢弃。 – 2009-12-13 14:47:43

+0

但是即使计算这样一个指针也是未定义的行为,不是吗? – 2009-12-13 15:31:52

4

*p = &c;指:

获取其在 编译时决定 链接时(感谢Mikeage)e.g,0x1234的作为例子的c在存储器中的地址。类型为int的指针,即*p被分配给0x1234,这听起来不合我的意思,我认为你应该这样做,p = &c然后*p将有值指向的地址c。因此*p将具有c分配给的值(这被称为解引用-通过在指针变量之前放置*然后您可以获得该值)。

在你的函数中,你试图增加p指向的值。

 
void function (int *p) 
{ 
    *p++; 
} 

// It would be called like this 
int c = 5; 
function(&c); // Now c would have 6! 

关键的一点是要通过引用传递这是什么参数&c一样。 如果省略引用传递这样的:

 
void function (int p) 
{ 
    p++; 
} 
// And call it like this 
int c = 5; 
function(c); // c is still 5 

现在c仍然是5,但功能本身c是6,但没有副本传递回了,因为它是在本地栈内增加内函数本身。

+0

迂腐,它只在编译时部分确定;取决于所得到的对象的操作系统和/或共享文库[我知道这不是一个短语],它可能是可重定位的。但你仍然得到一个+1为使用提问者的正确水平的细节(我当然没有......) – Mikeage 2009-12-13 13:35:17

+0

@Mikeage:谢谢:)那么,在编译时发生在连接权之前? ;)你就在那里......也许这个词应该是'在链接时',而不是编译时......感谢指出它! :) – t0mm13b 2009-12-13 13:43:50

+0

实际上,在加载时间;有些情况下,它可以在运行时重新定位 – Mikeage 2009-12-15 09:29:19

1

其他人已回答你的问题。我将补充一点,阅读指针声明的有用方法是这样的。假设我有以下声明:

int i; 

这真的很容易。这里,iint。现在,让我们说我有这样的:

int *pi; 

在这里,你可以说pi是一个指向int(这是正确的)。另一种看待它的方式是*piint,即当你的代码中有*pi时,*pi将是int类型。在了解之后,我认为很容易看出++pipi++不会增加int,因为pi是错误的类型。你想要(*pi)++。括号是必需的,因为在C中,运算符++比一元运算符*具有更高的优先级。既然你不使用任何增量的副作用,你也可以这样做:++*p

当然,就像所有的指针一样,pi必须指出一些对上述有用的东西是有意义的。