C指针基础(二)

这篇文章我们来谈谈指针在函数中的用法,即作为参数和作为返回值的用法。

指针作为参数

下面我们以一个比较经典的例子来说明这个问题——交换函数的实现来介绍这部分内容。下面是一种实现方法:

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

我们必须知道C语言中用值进行参数传递,所以函数调用中用作实际参数的变量无法改变,因此上面的方法是无效的。为了解决这个问题,我们不再传递变量ab作为函数的实际参数,而是提供&a&b,即指向ab的指针。我们通过间接引用符号*来间接改变ab中的值。下面是新的swap()函数:

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

另外我们需要再讨论另一个问题,那就是scanf()函数,对于这个函数,我想大部分人并不陌生。其实这个函数的第二个参数就是指针变量,因此我们在使用这个函数时,需要向其传递一个指针类型。很多人在使用这个函数时会产生一个误区:传递变量前必须有&符号,其实这是错误的,正如我们前面所说的,只要求是指针类型

int a, b;
int *p = &b;

scanf("%d", &a);  // 不要漏掉&符号
scanf("%d", p);   // p是指针类型,可以不用&符号

假如我们不想让函数对传进来的指针进行修改我们该怎么办呢?你可能会想到const修饰符,但是const该如何使用呢?你可能会想到以下几种方式:

void f1(const int *p);
void f2(int const *p)
void f3(int* const p);
void f4(const int* const p);

我们先来谈谈f1,它的参数是这样的const int *p,这种写法是限制我们不能修改指针所指向的对象的值。f2的作用和f1相同。而f3的作用是保护指针,即地址不被修改。我们刚刚说的是不能对指针进行修改,因此f3的这种写法符合我们的需要。其实这三种写法很好区分也很好记,对于f1f2const修饰的是*p,所以它保护的是指针所指向的值;对于f3const修饰的是p,所以它保护的是指针本身。对于f4,我想你已经猜出来了,它既对指针本身进行保护,也对指针指向的值进行保护。

  • 保护指针指向的值
void f(const int *p)
{
  int j;
  *p = 0;   /***错误***/
  p = &j;   /***合法***/
}
  • 保护指针本身
void f(int* const p)
{
  int j;

  *p = 0;   /***合法***/
  p = &j;   /***错误***/
}
  • 既保护指针,有保护指针指向的值
void f(const int* const p)
{
  int j;

  *p = 0;   /***错误***/
  p = &j;   /***错误***/
}

作为返回值

我们不仅可以为函数传递指针,还可以编写返回指针的函数。其实这很容易掌握,我们可以返回实际参数传入的指针的其中一个,也可以返回指向外部(全局)变量或者指向声明为static的局部变量的指针,但是我们不能返回指向局部变量的指针!

int *f(void)
{
  int i;
  ...
  return &i;
}

因为局部变量具有自动存储期限,函数调用时“自动”分配,函数返回时收回分配。因此一旦函数f返回,变量i就不存在了,所以指向变量i的指针是无效的。

参考资料

  1. somnik的博客:全局变量与局部变量的区别

  2. C语言程序设计现代方法, K.N.King, 人民邮电出版社

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值