【指针】C语言(5)

指针

指针是一个变量,其值为另一个变量的地址

  •  所有变量都有对应的内存位置,可通过&(连字号)运算符进行访问。
  • 指针是存储内存位置的直接地址的变量,可以通过指针访问对应的变量。
  • 在变量声明的时候,如果没有确切的地址可以赋值,一般为指针变量赋一个 NULL 值。赋为 NULL 值的指针被称为指针。NULL 指针是一个定义在标准库中的值为零的常量。

  • 指针声明:
int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;     /* 一个字符型的指针 */
  • 指针的基本使用:
#include <stdio.h>

int main()
{
    int var = 20;
    int *ip;

    ip = &var;

    printf("&var:\t%p\n", &var);
    printf("ip:\t%p\n", ip);
    printf("var:\t%d\n", var);
    printf("*ip:\t%d\n", *ip);

    return 0;
}

output:

&var:   0060FF08
ip:     0060FF08
var:    20
*ip:    20

数组指针

数组不能递增,而数组的指针可以递增

通过递增变量指针,可以顺序访问数组中每一个元素

#include <stdio.h>

const int MAX = 3;

int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;

   /* 指针中的数组地址 */
   ptr = var;
   for ( i = 0; i < MAX; i++)
   {

      printf("存储地址:var[%d] = %x\n", i, ptr );
      printf("存储值:var[%d] = %d\n", i, *ptr );

      /* 移动到下一个位置 */
      ptr++;
   }
   return 0;
}

output:

存储地址:var[0] = bf882b30
存储值:var[0] = 10
存储地址:of var[1] = bf882b34
存储值: var[1] = 100
存储地址:of var[2] = bf882b38
存储值:var[2] = 200

不知道数组长度,也可以打印数组:

#include <stdio.h>

const int MAX = 3;

int main ()
{
   int  var[] = {10, 100, 200};
   int  i, *ptr;

   /* 指针中第一个元素的地址 */
   ptr = var;
   i = 0;
   while ( ptr <= &var[MAX - 1] )
   {

      printf("Address of var[%d] = %x\n", i, ptr );
      printf("Value of var[%d] = %d\n", i, *ptr );

      /* 指向上一个位置 */
      ptr++;
      i++;
   }
   return 0;
}

output:

Address of var[0] = bfdbcb20
Value of var[0] = 10
Address of var[1] = bfdbcb24
Value of var[1] = 100
Address of var[2] = bfdbcb28
Value of var[2] = 200

指针数组

存储指针的数组

把 ptr 声明为一个数组,由 MAX 个整数指针组成。ptr 中的每个元素,都是一个指向 int 值的指针。

#include <stdio.h>

const int MAX = 3;

int main()
{
    int var[] = {10, 100, 200};
    int i, *ptr[MAX];

    for(i=0; i<MAX; i++)
    {
        ptr[i] = &var[i]; // 赋值为整数的地址
    }
    for(i=0; i<MAX; i++)
    {
        printf("*ptr[%d]:%d\n", i, *ptr[i]);
    }

    return 0;
}

output

*ptr[0]:10
*ptr[1]:100
*ptr[2]:200

也可以用一个指向字符的指针数组来存储一个字符串列表

#include <stdio.h>
 
const int MAX = 4;
 
int main ()
{
   const char *names[] = {
                   "Zara Ali",
                   "Hina Ali",
                   "Nuha Ali",
                   "Sara Ali",
   };
   int i = 0;
 
   for ( i = 0; i < MAX; i++)
   {
      printf("Value of names[%d] = %s\n", i, names[i] );
   }
   return 0;
}
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali

指针的指针

#include <stdio.h>
 
int main ()
{
   int  var;
   int  *ptr;
   int  **pptr;

   var = 3000;

   /* 获取 var 的地址 */
   ptr = &var;

   /* 使用运算符 & 获取 ptr 的地址 */
   pptr = &ptr;

   /* 使用 pptr 获取值 */
   printf("Value of var = %d\n", var );
   printf("Value available at *ptr = %d\n", *ptr );
   printf("Value available at **pptr = %d\n", **pptr);

   return 0;
}
Value of var = 3000
Value available at *ptr = 3000
Value available at **pptr = 3000

传递指针给函数

 获取当前时间的函数:

#include <stdio.h>
#include <time.h>

void getSeconds(unsigned long *par);  //获取当前时间

int main ()
{
   unsigned long sec;  //存储时间


   getSeconds( &sec ); //传入变量的指针

   /* 输出实际值 */
   printf("Number of seconds: %ld\n", sec );

   return 0;
}

void getSeconds(unsigned long *par)
{
   /* 获取当前的秒数 */
   *par = time( NULL );
   return;
}

output:

Number of seconds: 1539228344

传递数组指针给函数:

传入数组指针和数组大小,返回数组平均值

#include <stdio.h>

float getAverage(int *arr, int size);  //传入数组指针和数组大小,返回数组平均值

int main ()
{
   int arr[] = {1, 2, 3, 2, 1};
   float avg;

   avg = getAverage(arr, 5);
   printf("average is %f\n", avg);

   return 0;
}

float getAverage(int *arr, int size)
{
    float avg;
    int i, sum = 0;  //注意!sum一定要赋初值

    for(i=0; i<size; i++)
    {
        sum += arr[i];
    }
    avg = (float)sum/size;  //转换类型为float

    return avg;
}
average is 1.800000

从函数返回指针 

  • C 语言不允许返回一个完整的数组作为函数的参数。 
  • C 允许您从函数返回指针。为了做到这点,您必须声明一个返回指针的函数
  • C 语言不支持在调用函数时返回局部变量的地址,除非定义局部变量为 static 变量。

下面的函数会生成 10 个随机数,并使用表示指针的数组名(即第一个数组元素的地址)来返回它们:

#include <stdio.h>
#include <time.h>
#include <stdlib.h> 
 
/* 要生成和返回随机数的函数,函数变量类型为指针 */
int * getRandom( )
{
   static int  r[10];
   int i;
 
   /* 设置种子,srand为stdlib库函数,time为time库函数 */
   srand( (unsigned)time( NULL ) );
   for ( i = 0; i < 10; ++i)
   {
      r[i] = rand();
      printf("%d\n", r[i] );
   }
 
   return r;
}
 
/* 要调用上面定义函数的主函数 */
int main ()
{
   /* 一个指向整数的指针 */
   int *p;
   int i;
 
   p = getRandom();
   for ( i = 0; i < 10; i++ )
   {
       printf("*(p + [%d]) : %d\n", i, *(p + i) );
   }
 
   return 0;
}
1523198053
1187214107
1108300978
430494959
1421301276
930971084
123250484
106932140
1604461820
149169022
*(p + [0]) : 1523198053
*(p + [1]) : 1187214107
*(p + [2]) : 1108300978
*(p + [3]) : 430494959
*(p + [4]) : 1421301276
*(p + [5]) : 930971084
*(p + [6]) : 123250484
*(p + [7]) : 106932140
*(p + [8]) : 1604461820
*(p + [9]) : 149169022

函数指针

函数指针是指向函数的指针变量。

函数指针的使用与函数一样,相当于起了个别名:

#include <stdio.h>

int max(int x, int y)
{
    return x > y ? x : y;  // 三元运算符
}

int main ()
{
   int a, b, c, m;
   //将函数地址赋给函数指针变量,注意函数指针的定义形式
   int (*p)(int, int) = &max;  //max亦可

   scanf("%d %d %d", &a, &b, &c);
   m = p(p(a, b), c);
   printf("the max number is %d\n", m);

   return 0;
}

回调函数

回调函数是指使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数传入别人(或系统)的函数中,由别人(或系统)的函数在运行时来调用的函数。

#include <stdlib.h>
#include <stdio.h>

// 函数指针作为参数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
    {
        array[i] = getNextValue();
    }    
}

// 获取随机值的回调函数
int getNextRandomValue(void)
{
    return rand();
}

int main(void)
{
    int myarray[10];
    populate_array(myarray, 10, getNextRandomValue);  //传入回调函数
    
    for(int i = 0; i < 10; i++)
    {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值