C-指针

作者: 小石头呢 | 来源:发表于2019-08-04 16:30 被阅读0次

指针:

  • 解决代码块与代码块之间的数据传递
  • 一个变量的地址称为该变量的指针

指针变量:

  • 用来存放另一个变量的地址的变量
  • 指针变量的类型由指向的那个变量的类型决定
  • 定义指针变量的时候必须赋初值,如果暂时没有初值就赋值NULL(0),没有被初始化的指针被称为失控指针(野指针)
  • 内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置
  • 指针变量只能存地址
  • 指针变量本身永远只占据8个字节的内存空间(64位系统)

*&

  • *用于定义指针变量,标识该变量是一个指针变量
  • *除了定义指针变量外,都是访问指针变量中可用地址的值
  • &是取一个变量的地址

一.指针的算术运算

C 指针是一个用数值表示的地址。因此,您可以对指针执行算术运算

我们喜欢使用指针代替数组,因为变量指针可以递增,而数组不能递增,数组可以看成一个指针常量

数组名并不是一个变量,没有分配内存空间,指针变量是有内存空间

定义一个数组,系统会分配内存空间,可以存值

定义一个指针变量,只为变量本身分配分配8个字节内存空间,不会为他分配可以存值的内存空间,无法存值

1.递增一个指针(递减一个指针同理)

//递增变量指针,以便顺序访问数组中的每一个元素
#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;
}

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

2.指针的比较

  • 指针可以用关系运算符进行比较,如 ==、< 和 >。

  • 如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。

//只要变量指针所指向的地址小于或等于
//数组的最后一个元素的地址 &var[MAX - 1]
//则把变量指针进行递增
#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;
}

//运行结果
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

二.指针数组

int *ptr[MAX];把 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("Value of var[%d] = %d\n", i, *ptr[i] );
   }
   return 0;
}

//运行结果
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200

指针的一些复杂说明:

三.指向指针的指针

  • 指向指针的指针int **变量名;是一种多级间接寻址的形式,或者说是一个指针链。

  • 通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

//当一个目标值被一个指针间接指向到另一个指针时
//访问这个值需要使用两个星号运算符
#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

四.传递指针给函数

C 语言允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。

#include <stdio.h>
 
/* 函数声明 */
double getAverage(int *arr, int size);
 
int main (){
   /* 带有 5 个元素的整型数组  */
   int balance[5] = {1000, 2, 3, 17, 50};
   double avg;
 
   /* 传递一个指向数组的指针作为参数 */
   avg = getAverage( balance, 5 ) ;
 
   /* 输出返回值  */
   printf("Average value is: %f\n", avg );
    
   return 0;
}

double getAverage(int *arr, int size){
  int    i, sum = 0;       
  double avg;          
 
  for (i = 0; i < size; ++i)
  {
    sum += arr[i];
  }
 
  avg = (double)sum / size;
 
  return avg;
}

//运行结果
Average value is: 214.40000

五.从函数返回指针

  • C 不支持在调用函数时返回局部变量的地址,除非定义局部变量为 static 变量。

  • 因为局部变量是存储在内存的栈区内,当函数调用结束后,局部变量所占的内存地址便被释放了,因此当其函数执行完毕后,函数内的变量便不再拥有那个内存地址,所以不能返回其指针。

  • 除非将其变量定义为 static 变量,static 变量的值存放在内存中的静态数据区,不会随着函数执行的结束而被清除,故能返回其地址。

//生成 10 个随机数,并使用表示指针的数组名(即第一个数组元素的地址)来返回它们
#include <stdio.h>
#include <time.h>
#include <stdlib.h> 
 
/* 要生成和返回随机数的函数 */
int * getRandom( ){
   static int  r[10];
   int i;
 
   /* 设置种子 */
   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;
}
  • 计算机并不能产生真正的随机数,而是已经编写好的一些无规则排列的数字存储在电脑里

  • 把这些数字划分为若干相等的N份,并为每份加上一个编号用srand()函数获取这个编号

  • 然后rand()就按顺序获取这些数字,当srand()的参数值固定的时候,rand()获得的数也是固定的

  • 所以一般srand的参数用time(NULL),因为系统的时间一直在变,所以rand()获得的数也就一直在变,相当于是随机数了。

六.函数指针

https://www.jianshu.com/writer#/notebooks/29146076/notes/41287791/preview

相关文章

  • C-指针

    指针: 解决代码块与代码块之间的数据传递 一个变量的地址称为该变量的指针 指针变量: 用来存放另一个变量的地址的变...

  • C-指针

    1.从变量名处起,根据运算符优先级结合,一步一步分析 参考:https://blog.csdn.net/soonf...

  • C-指针讲解

    指针的类型是什么: 将指针的名字去掉即可 指针指向的是什么类型: 将指针的名字以及指针左边的*去掉 指针指向了哪里...

  • C-关于指针

    ​ c和指针的关系十分密切,所以在本文,我们会详细的谈谈指针。这边我会结合<>这本书的内容来介绍它。 ...

  • 0876-链表的中间结点

    链表的中间结点 方案一 使用快慢指针 借助单链表实现 C-源代码

  • 链表--回文字符串

    字符串通过链表存储 a->b->c->b->a使用双指针形式,慢指针向后走一步,快指针向后走两步。当快指针走到尾结...

  • 一分钟技能

    Recognize these scenarios? When Sally got a C- on a test,...

  • 反转一个链表的思路

    输入:A->B->C->D->E->NULL 输出:E->D->C->B->A->NULL 第一种使用while循...

  • iOS NavigationController栈跳转

    3种跳转方式 a->b->c-> 实现c->a 1.通过修改导航栈来跳转 先修改栈再pop 2.通过popT...

  • 2018-07-31spring cloud

    组合注解 @SpringCloudApplication eureka 高可用 a->b->c->....->a ...

网友评论

      本文标题:C-指针

      本文链接:https://www.haomeiwen.com/subject/ikvkdctx.html