C语言学习09.指针

指针(Pointer):就是内存地址,即单元编号。
指针变量,存放指针的变量,其值就是某个地址单元的地址。
指针变量的存储空间需要连续的4个字节单元,如果系统是32位的,则指针变量固定是32位。类型为无符号整数(不是整型),保存变量所占存储空间的首字节的地址编号。
指针就是储存别的变量的内存地址的一种变量。
内存的第一个可用的标号是1而不是0,地址为0的内存空间一般不可用。

int i;            // 定义整型变量 i。
int *p            // p 为指向整型数据的指针变量。
                  // 基类型:表示指针所指向的变量的类型 。
                  //指针变量名为p1,而不是*p1 。
                  //*指针运算符,或间接访问运算符,获取指针所指向的数据。
                  //&取地址符运算符,只能用于变量,不能用于表达式或常量或说明为register的变量。
int a[n];         // 定义整型数组 a ,它有n 个元素
int *p[n];        // 定义指针数组 p ,它由n 个指向整型数据的指针元素组成
int (*p)[n];      //  p 为指向含n 个元素的一维数组的指针变量
int f();          //  f 为带回整型函数值的函数
int *p();         //  p 为带回一个指针的函数,该指针指向整型数据
int (*p)();       //  p 为指向函数的指针,该函数返回一个整型值
int **p;          //  P 是一个指针变量,它指向一个指向整型数据的指针变量
int *pointer1, *pointer2, *pointer3;   // 声明三个指针变量 
  • 如果:
    int number = 16;
    int *pointer = &number;
  • 那么:
    • 对于变量 number 来说
      number:number的值
      &number:number的内存地址
    • 对于指针 pointer 来说
      pointer:指针的值,也就是其所指向的另一个变量的内存地址。也就是number的地址,即&number。
      *pointer:指针所指向的内存的值,也就是number的值.

看一个取指针指向的地址的值的例子:

int main()  
{  
   int userAge(16);  
   int *ptr(0);    
   ptr= &userAge;  
   cout << "指针变量ptr所指向的变量的值是  " << *ptr << endl;    
   return 0;  
}  

程序执行到 cout << *ptr 时依次做了以下的操作:
找到名字是ptr的内存地址空间
读取ptr中的内容
"跟着"指针指向的地址(也就是ptr的值),找到所在地址的内存空间
读取其中的内容(变量userAge的值)

当变量被定义时,大致说来程序其实做了两步:
程序请求操作系统分配给它一块内存空间。用专业术语说就是:内存分配。
用一个数值来填充这块内存空间,用术语说就是:变量的初始化。

内存泄露:野指针,或者内存空间的唯一标识是一个指针,然后指针删了或者指向了别处,此处的内存是无法再找到的。
先删掉指针所指的东西,再删掉指针,或者指向一个无效的地址(0)。

通常在以下三种情况下应该使用指针:
想要自己控制内存空间的分配和释放
在多个代码块中共享一个变量
在多个元素间选择

指针运算

1)指针变量加(减)一个整数:
例如:p++、p--、p+i、p-i、p+=i、p-=i
一个指针变量加(减)一个整数并不是简单地将原值加(减)一个整数,而是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数加(减)。
+表示向高地址方向移动,-表示向低地址方向移动。
加的单位取决于指针的基本类型,移动一个存储单元。
*++s 取指针变量加1后的内容
S++取指针变量所指的内容后S再加1
(
s)++指针变量指的内容加1

2)指针变量赋值:将一个变量的地址赋给一个指针变量。

p=&a;        (将变量a的地址赋给p)  &取地址符运算符,只能用于变量,不能用于表达式或常量。
p=array;      (将数组array的首地址赋给p)
p=&array[i];   (将数组array第i个元素的地址赋给p)
p=max;       (max为已定义的函数,将max的入口地址赋给p)
p1=p2;        (p1和p2都是指针变量,将p2的值赋给p1)
注意:不能如下:
p=1000;

3)指针变量可以有空值,即该指针变量不指向任何变量:
p=NULL; //NULL是在stdio.h中定义的常量,其值为0.
指针变量定义之后没有赋初值,其值是不确定的,指向一个不确定的单元。也就是野指针。

4)指针与指针相加没有意义,相减得到两个指针间隔的某类型数据的个数。

5)两个指针变量比较:如果两个指针变量指向同一个数组的元素,则两个指针变量可以进行比较。指向前面的元素的指针变量“小于” 指向后面的元素的指针变量。
如果p和q是指向相同类型的指针变量,并且两者指向同一段连续的存储空间,p的地址值小于q的地址值,则表达式p的结果为1,否则为0。
所以,需要指向同一个连续的内存空间,并且只有相同类型的指针变量才能比较。

指针常量和常量指针

常量指针 int* const p1 = &b;
//地址可以变,指向的内容不能通过p1改,(在p1眼中b是常量),只能通过修改地址再修改内容
p1 = &a;//对的
p1 = a; //错的
指针常量 int const
p2 = &c;
//指向的地址不能变(地址跟随一生),内容可以变,必须初始化
p2 = &a;//错的
*p2 = a; //对的

数组和指针

数组名代表了数组的首地址,是地址常量,或称为常量指针。常量指针不能运算。Int a[];完全等效于int* const a;
1、 数组元素的指针
2、 指针数组
3、 数组名其实就是指向数组首元素的指针常量。数组名是常量指针,不能变的,是元素的指针常量,因为指向的地址不能变。元素可以变。
4、 数组的指针(飘过)
a[3]等价于(a+3)
ptr[3]等价于
(ptr+3)

函数和指针

  1. 指针作为返回值:返回一个地址,但是不要返回自动变量的地址,因为自动变量会在函数结束之后释放。
  2.   指针作为函数的参数:通过传递地址,使形参改变实参的值成为可能。void s(int *q);
      设计一个函数时,如果函数带有指针类型形参,并且确定在函数内部不需要对指针形参所指向的数据进行修改,那么将该指针形参定义为常量指针,即加一个const.。
      在c 语言中,调用函数时实参的值传递给形参,即传值,不是传址,即函数形参为指针变量,也是实参的值传递给形参变量。
    
  3. 函数指针:即函数的入口地址,也就是构成函数的二进制指令的起始位置。在调用函数就是跳转到函数入口地址处执行函数代码。函数名就是函数的入口地址。
    重点掌握声明函数指针类型和定义函数指针变量的语法形式。
    viod(p3)();//定义一个函数指针变量p3,p3可以指向所有返回值为void,形参为空的函数。
    int(
    p4)(int, int)=add;//定义函数指针变量并初始化。
    typedef int(MY_FUN)(int,int);//声明函数指针类型,类型为MY_FUN,该类型代表函数原型为int()(int,int)的所有函数。
    MY_FUN p6=add;//通过函数指针类型定义函数指针变量。
    被调函数第一次被调用时会初始化(定义初始化),第二次被调用时不会,即定义初始化的语句会被忽略。

指针与字符串

可以用一个字符串的首字符的指针代表整个字符串,因为字符串的结尾都是‘\0’。
常量都是存放在内存中的常量区中,这块内存空间的数据是只读的。
字符串常量本质就是其首字母的指针
Char str[]=”abcdef”;
Char* p1=”abcdef”;

指针的强制类型转换

由于任何基类型指针的存储形态都一样,所以不同类型指针之间可以随意进行强制类型转换。
空类型指针(void),注意不是空指针(NULL)常量,void就是不确定基类型的指针类型,它可以代表其他一切基类型的指针。不能对void*指针进行指针运算。
一切皆空,但空不是一切。

main函数的参数

main (int argc,const char argv[])
char
argv[]:指针数组
char (*argv)[]:数组指针
argc:命令行中参数的个数(包含命令本身)
argv:具体的命令行参数的值(字符串)

其他:

用变量a给出下面的定义
答:a) 一个整型数(An integer)
b) 一个指向整型数的指针(A pointer to an integer)
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)
d) 一个有10个整型数的数组(An array of 10 integers)
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer
argument and return an integer )

答案是:

a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
C语言学习09.指针_第1张图片
图片来自于物联网
C语言学习09.指针_第2张图片
图片来自于物联网

你可能感兴趣的:(C语言学习09.指针)