C基础——指针

来源:互联网 发布:clojure编程 中文 编辑:程序博客网 时间:2024/04/27 18:16



谨记:指针就一个作用,:能够根据一个地址值,访问对应的存储空间。
0、指针概念
指针:指针是一个地址,可以通过获取地址来操控(所谓的操控即:取值赋值操作)此地址中存储空间的值。

1、指针变量
作用:存储内存地址的变量(指针变量占用8个字节存储空间),根据这个地址就可以操作(取值或赋值)这块存储空间中的内容。
格式   类型标识符  *变量名   

int *p;//这里的int意味着指针变量p只能只想整形数据;定义指针变量的*只是一种象征,表示是指针类型。

初始化                  

int *p = 10;//把10赋值给了指针变量p所指向的存储空间。这里的*表示访问指针变量n指向的存储空间,并作赋值操作int *p = &a; // <=> int *p; p = &a;假设a的地址是ffc5,那么*p表示从ffc5开始取4个字节,因为*p前面已经定义好了int类型,int类型占4个字节,那么*p就会取4个字节。即你给它一个地址,它就会从这个地址开始存放/读取多少个数据。

注意   指针变量只能用来存地址,指针没初始化不要随便用来访问存储空间。

指针访问的空间大小
   指针访问的空间大小只与指针的返回值有关,和变量没关系。
    eg: char a='A';
           int *p=&a;
 代表指针p访问的空间大小为4个字节。
 清空指针:p = 0 或者 p = NULL。

2、指针的加法

在数组中常常会使用*(p+i)这种形式,指针可以和数字相加,指针的类型决定了当指针+1时跳过多少个字节。比如int 4 ,double 8, char 1.....
指针变量占的空间大小:
不管指针指向什么类型的数据,它存储的都是内存地址。所以所有的指针变量所占的空间都是一样的,与指针变量的类型无关,只跟编译器有关。64位编译器中,指针变量占8个字节。

3、指针与数组
      利用指针来接收一个数组,指针变量指向的了数组的首元素(数组的地址),即数组名就是数组的地址也是数组首元素的地址。

eg:
    ag[]={4,5,6,7,8};
    int *p=&ag[0]; // 或者p=ag;
   /* 
    p-->&ag[0]
    p+1 -->&ag[1]
    p+2 -->&ag[2]
    p+i -->&ag[i]
    */
    指针加1 代表指针指向下一个数组地址(加1究竟加多字节数取决指针类型,eg:int类型就加4,char类型就加1)。
     数组元素的访问方式:
      1> 数组名[下标]   ages[i]
      2> 指针名[下标]    p[i]
      3> *(p+i)
eg:
#include<stdio.h>int main(){     int ages[5]={10,9,8,68,6};     int *p;     p=ages;//数组名就是数组地址,也是数组首元素地址。     for(int i=0;i<5;i++)//其中5也可以写成sizeof(ages)/sizeof(int);     {          printf("ages[%d]=%d",i,p[i]);      }}

4、指针与字符串
1> 利用数组定义:
 char name[]="itcat";
 char name2[]="itcat"; // 开闭新的内存存储空间
 特点:字符串里的字符可以修改。//此值放在栈内,属于字符串变量
 使用场合:字符串内容需要经常修改。

 2> 利用指针:
 char *name="itcast";
 char *name2="itcast"; // 使用*name的存储空间,不会新增存储空间,指针name2指向第一个字符的地址,既字符i的地址
 特点:字符串其实是一个常量字符串,里面的字符无法修改、//因为此值放在常量区内,会将此值缓存,属于字符串常量
 使用场合:字符串内容不需要修改,且字符串内容要经常使用。
eg:
char *name1 = "abc";      *name1 ='A';//指针name1所指向的存储空间的值无法进行修改      printf("%s",name1);//不能打印出来
int main()    {     char *name="asd";     printf("%s\n",name); //从name的第一个地址开始输出,直到遇到\0后就停止输出。    //printf("%c\n",*name);//输出指针所指向的一个字符。    }

错误代码:

char *p="asd";     *p="ddd";
以上代码也错误,有两个错误:
          1> 因为指针p的返回值是char型,只能赋值字符型,而*p="ddd",代表将字符串赋值给p,因此错误。
          2> char *p="asd"; 代表定义的是字符串常量,常量不能被更改。
总之:用数组形式s[]定义的是字符串变量,可以像数组一样访问,可以修改字符串的内容,比如s[0] = 'A'。
用指针形式*p定义的是字符串常量,不可以修改字符串的内容(比如p[0] = 'A';或 *p = "ABC";),但是可以指向一个新的字
串(比如 p = "ABC";),也可以指向一个可变字符串,比如p = s;就可以修改这个字符串中的内容了 p[0] = 'A'; 如果再次指向一个新定义的字符串(比如 p = "abc"),那还是字符串常量,不可改。

5、指针与函数
指向函数的指针
 1> 定义形式:函数的返回值类型 (*指针变量名)(形参1,形参2, ...);
    int (*p)(); // 代表指针p指向一个函数,函数的返回值是int类型。
     void (*p)();   // 指针名p 指向一个函数。
     p=test; // test是函数名 ,函数名就相当于地址(整个函数的入口)。
     (*p)(); // 调用指针所指向的存储空间。

  2> 调用方法:
     (*p)(); // 调用指针所指向的存储空间;
     test();  // 直接使用函数名调用。
eg:
#include <stdio.h>void test(){     printf("调用了test函数\n");}int main(){     void (*p)();     p = test;     p();     (*p)();//利用指针变量间接调用函数       test(); //直接调用函数。     return 0;}
 注意: a.由于这类指针变量存储的是一个函数的入口地址,所以对它们作加减运算(比如p++)是无意义的。
             b.指向函数的指针变量主要有两个用途:调用函数,将函数作为参数在函数间传递。
返回指针的函数: 类型名 * 函数名(参数列表)  
char *test ()//代表test函数返回的是指针(也就是返回地址)      {            return "rose";      } int main()       {             char *name = test();             return 0;        }
6、int const *p 和 int *const p的区别
   int const *p : 1> const修饰的是*p,因此*p 是常量,不能通过*p 修改p所指向的存储空间的值
                       2>P是变量,可以被赋值,p所指向的地址可以变化。
   int *const p:1>p是常量,其所指向的地址不能变化。
                        2>*p 是变量,其所指向的存储空间的值可以变化
      
0 0