指针-笔记

什么是指针?

  指针是一类数据类型的统称.

  这种类型的数据用来专门存储内存中的一块空间的编号,用于表示这一段内存.以实现通过内存地址(编号)完成各种运算.也就是一个指针指向一块内存空间,指针把这一块空间的第一个Byte的空间的地址存在指针的右值中.指针自己也是有内存空间和内存地址的.

  数祖名也是个指针,而且是个常量指针. 该指针指向数组在内存中的那块空间,并把数组第一个字节的地址存在指针的右值中.该地址和数组第一个元素的首地址相同. 指针的类型有很多,其他在下面体现,这里就不一一举例了.

常见的两种和指针有关的操作符:

  #1 * 定义指针的时候相当于类型说明符,说明接下来定义的变量是指针类型; 在使用指针变量时 *p 代表把指针变量p指向的内存空间的值去除;

  int a, *p, p = a; *p = 5;

  在定义一个指针时 int * p中的 *  并不是算术运算符乘, 像这样一词多义的情况,在C语言中还有很多. 在这里 * 是指针类型说明符, 说明p是一个指针, 这里的int 代表指针p指向的内存空间存放的数据是int 类型的.*p = 5, 这里的 * 又是另一个意思, 是一个间接引用运算符.它代表取出指针指向的空间, 在这里是把int类型数据5拷贝到指针p指向的内存空间中, 也就是把变量a的右值改成5.

  #2 & 取指针运算符

  之前学习scanf(“%d”, &a)函数时常用的”&”符号,其实就是求指针运算符,取得一个指针指向变量a的空间,&a把a的空间的手地址存放在&a的右值中.通过这个指针可以找到a的地址,从而把接受到的数据按照%d的格式存放在a的空间.

指针的优点:

  a.为函数提供修改调用变量的灵活手段;

  b.让函数有多个返回值

  c.可以改善某些子程序的效率

  在数据传递时,如果数据块较大(比如说数据缓冲区或比较大的结构),这时就可以使用指针 传递地址而不是实际数据,即提高传输速度,又节省大量内存。

  d.为动态数据结构(如二叉树、链表)提供支持

二级指针

  如果一个指针指向另一个指针,则称这个指针为二级指针. 二级指针的右值存放的是一级指针的地址.

  定义指针时, 变量名前有几个*就是几级指针.

  <其他待补充...>

一维数组指针

  即指向一维数组的指针.

  int a[5] = {1, 2, 3, 4, 5}; int *p =a;

  指针变量p指向数组a的空间,a的首地址作为值存放在p的右值中.这是指针变量p可以代替数祖名使用,例如p[0], 相当于a[0].但由于p是变量,所以可以使用++ -- 等运算,但是数组名是常量,则不可以这样运算.

二维数组指针

  指向二维数组的指针.内容存放的是数组的行首地址.

  int arr[3][5]; int (*p)[5] = arr;

  二维数组指针是单个的变量. p + 1, 代表第二行的指针.

*注意: #1 *p左右的括号不可少, 如果少了括号则变成二维指针数组

     #2 指定列宽[5]不可少, 这是要告诉编译器该数组指针指向的数组结构,其列宽是5.

一维指针数组

  即:数组的内容存放的是指针变量

  int a, b, c;

  int *p[3] = {&a, &b, &c};

指针之间的运算

  当两个指针指向同一个数组, 两个指针想减的结果说明两个指针相隔了几个元素.p1 - p2 > 0 说明p1在高地址位, 相反则在低地址位. p1 - p2 == 0则说明两个指针指向了同一个元素.

  两指针之间只有减法运算有意义,其他运算是没有意义的.

数祖名访问二维数组的每个元素

  如前面所说,数组名也是个指针,所以通过数组名也可以访问数组中的每个成员.

  int a[3][5];

  a + i : 可以代表行的首地址, 也就是行指针

  a[0] + j :  a[0] + j可以代表列指针

  (*(a + i) + j) : 可以代表任意一个元素的地址,所以

  *(*(a + i) + j): 可以取出任意一个元素的值

字符串指针

  指向字符串的指针.

1. 定义方法:char *变量名 = ”字符串内容“;// “字符串内容”是常量,保存在内存中的常量区

作用:用来保存一个字符串,保存了字符串的首地址

2. 字符串指针不能从键盘接收一个字符串,但是可以通过malloc()先申请一定长度的内存空间,用来接收键盘输入的字符串。

现在可以保存字符串的几种方式;

#1 字符数组

  把字符串通过数组保存到栈中,内容是可读可写的,也就是说可以改变字符数组的内容

#2 二维字符串数组

#3 字符串指针:

  指向字符串常量的首地址,字符串常量是只读的,不可以更改其内容。但是字符串指针可以重新指向其他字符串地址。

#4 char类型指针数组

  char *p[3] = {"Hello", "ZJL", "Hello"};

  数组每个元素都指向一个字符串.

指针函数

  返回值为指针的函数称为指针函数.

定义:

  类型说明符 *函数名(形参列表){

    函数体;

  }

函数名前加*说明返回的是指针,类型说明符说明返回的指针指向的空间内元素的类型.

函数指针

  一个函数总是占用一段连续的内存空间,函数名就是该函数空间的首地址.我们把这种指向函数的指针变量称为”函数指针”;

函数指针变量的定义:

  返回值类型 (*变量名)(函数的参数);//可以省略形参名,但不能省略形参类型

注意:

1)函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可 使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。

2)函数调用中"(*指针变量名)"的两边的括号不可少,其中的*不应该理解为求值运算,在此处它 只是一种表示符号

野指针

  定义指针时,没有初始化该指针. 又或者指针指向目标丢失(例如malloc等函数生成的内存空间被free后),这样的指针叫野指针.

  定义指针变量的同时如果没有指向一个确定的目标,最好初始化为NULL,用完指针后也将指针变量设置为NULL.

内存泄漏:

  int *p = (int *)malloc(16);p在棧中, malloc(16)在堆中

解决方法:p释放前,先释放堆中的malloc(16)申请的空间

free函数使用:先导入库文件

  free(p);//p要释放的空间的首地址,free代表p指向的那块空间可以被重新利用

  p = NULL;//把释放空间后的指针指向NULL,避免p还指向之前的内存空间

1. 常见的内存分配的函数

malloc calloc realloc 在堆中分配空间

###malloc

  void *malloc(unsigned size),包含在库函数sodlib.h中,作用是在内存的队区分配一个大小为size连续的内存空间,如果分配成功,函数返回新分配内存的首地址,否则,返回NULL.注意:鉴于上述这点,一般在写程序需要判断分配内存是否成功

注意:

  malloc申请的空间,如果该空间不初始化(赋值),则空间内容是不确定的.

  memset(p, ‘A’, 16);这个函数可以给malloc申请的空间初始化,内容全部为’A’,其中p为接收malloc申请空间的指针,16为空间大小.

###calloc

  clloc(块数,每块的长度),分配指定块数的连续的内存空间.分配成功则返回空间首地址,否则返回NULL.

注意:

  calloc分配内存空间成功后,会自动初始化分配的内存空间,初始化为0.

###realloc

  realloc可以给已经存在的空间重新分配大小,但地址可能会改变.之前空间的数据不会丢失,会被拷贝到新的空间.所以在使用该函数时,需要把返回值重新赋值给之前的指针.

时间: 2024-12-29 11:38:15

指针-笔记的相关文章

C和指针笔记 3.6链接属性

链接属性决定如何处理在不同文件中出现的标识符.标识符的作用域也它的链接属性有关,但这两个属性并不相同. 没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体. internal链接属性的标识符在同一个源文件内的所有声明中都指同一个实体,但位于不同源文件的多个声明则分属不同的实体.最后,属于external链接属性的标识符不管声明多少次.位于几个源文件都表示同一个实体. 图3.2的程序骨架通过展示名字声明的所有不同方式,描述了链接属性.在缺省情况下,

C和指针笔记 3.7 存储类型

变量的破碎类型是指存储变量值的内存类型.变量的存储类型决定变量何时创建.何时销毁以及它的值将保持多久. 有三个地方可以用于存在变量:普通内存.运行时堆栈.硬件寄存器. 变量的缺省存储类型取决于它的声明位置.凡是在任何代码块之外声明的变量问题存储于静态内存中,也就是不属于堆栈的内存,这类变量称为静态变量.对于这类变量,你无法为它们指定其他存储类型.静态变量在程序运行之前创建,在程序的整个执行期间始终存在.它始终保持原先的值,除非给它赋一个不同的值或者程序结束. 在代码块内部声明的变量的缺省存储类型

C和指针笔记 3.8 static关键字

当用于不同的上下文环境时,static关键字具有不同的意思. 当它用于函数定义时,或用于代码块之外的变量声明时,static关键字用于修改标识符的链接属性,从external改为internal,但标识符的存储类型和作用域不受影响.用这种方式声明的函数或变量只能在声明它们的源文件中访问. 当它用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量修改为静态变量,但变量的链接属性和作用域不受影响.用这种方式声明的变量在程序执行之前创建,并在程序的整个执行期间一起存在,而不

c指针 --笔记2返回指针值的函数

返回指针值的函数 一般带回指针值的函数,定义形式为: int *a (int x, int y); 看这个经典案例: #include <stdio.h> int main(int argc, char const *argv[]) { double score[][4] = {{60.0, 70.0, 80.5, 20.1}, {60.0, 70.0, 80.5, 21.1}, {60.0, 70.0, 80.5, 22.1}}; double *search(double(*pointer

c++指针 笔记

我们定义一个指针就一定要用他保存一个内存地址,加入我们不这样做,那么该指针就是一个失控指针他可以指向任何地址,并且对该地址的数值进行修改或删除,后果是非常可怕的解决办法是将该指针初始化为0,即p = 0:该语句是将p所保存的地址清零,(即让p指向00000000这个地址,这个地址是不会存放任何数据的,因此我们对它进行的任意操作都不会产生严重后果)这样p就不会因为我们的疏忽而修改它指向的地址(随机)的值 由于指针类型不同决定了指针的运算方式不同,所以我们不能将一种类型的指针赋给另一种类型的指针 可

C指针笔记

重新学习C语言,整理一篇关于C语言指针的文章是很有必要的. 首先是指针的理解:指针是一个变量,存放内存地址的一个变量. 先由一段代码引出: #include <stdio.h> #include <stdlib.h> int main() {     int year = 2017;     int * prt_year = NULL;     prt_year = &year;     printf("今年是%d年",*prt_year);     r

20160921晚 指针笔记

1 为什么要用指针   因为C要操作内存. 2 指针也是要占用内存的. 3  指针的表示:首地址  +  长度   int*   char* 4   哪些方面会用到指针呢?以下方面会用到指针: 4.1函数传参:指针占用内存空间是一定的,参数有大有小,大的参数用指针,就能节约内存空间,程序运行快. 4.2跨函数的值修改 4.3数组是一个特别的指针:const int *pArray;常量指针 4.4数据的一些结构:链表,二叉,等. 5 平常开发中,只用到2级指针.3级就等着被开除. 6 void*

c++指针笔记一

左值和右值的区别:左值就是在赋值中可以放在赋值操作符两边的值,比如: int a = 1; double b = 2.0 a = b; b = a; 这里a和b都是左值,一切变量都是左值,但const量是例外. 而右值则是只可以放在赋值操作符右边的值,比如: int a = 0; char *b = "hello"; 3 = a; // ERROR "howdy" = b // ERROR 这里3和"howdy"都是右值,所以不能放在赋值操作符左

C语言 二维数组与指针笔记

今天分析了C语言二维数组和指针的基本理解,感觉有点懵...代码记录一下,如果有大神临幸发现哪里有误,欢迎指正~~~ #include <stdio.h> #include <stdlib.h> #include <string.h> //void func(int p[][]) //这样写等同于void func(int **p) p++移动了四个字节,(*p)++移动了四个字节,不符合二维数组规律 //{ //} //列优先输出的函数(即竖着输出) void func