linux下c语言指针部分的一个总结

    xiaoxiao2021-03-25  43

    1、指针的定义与初始化

    如何理解指针? 首先要在回答指针是什么时一定要说指针是变量,这样的话,指针就有了变量的特性。  (1) 系统为指针分配内存空间;  (2) 指针有自己的地址;  (3)指针能够存值,但这个值比较特殊–地址。  指针的字节长度: 任何类型指针的长度都是4个字节(32)系统,指针变量是一个地址,在操作系统中地址的长度是固定的。

    2、* 与&运算符详解(用于取内容(*)和取地址(&)两种运算。)

    指针的类型和指针所指向的类型  (1)指针的类型  从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型,这是指针本身所具有的类型。让我们看看例子中各个指针的类型。  (1)int * ptr; //指针的类型是int*  (2)char * ptr; //指针的类型是char*  (3)int *ptr; //指针的类型是int *  (4)int (* ptr)[3]; //指针的类型是int(*)[3]  (5)int * (* ptr)[4]; //指针的类型是int*( *)[4]

    (2)指针所指向的类型  当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当作什么来看待。从语法上看,只须把指针声明语句中的指针名字和名字左边的指针声明符“*”去掉,剩下的就是指针所指向的类型。例如:  (1)int*ptr; //指针所指向的类型是int  (2)char*ptr; //指针所指向的的类型是char  (3)int * * ptr; //指针所指向的的类型是int*  (4)int (*ptr)[3]; //指针所指向的的类型是int()[3]  (5)int* (* ptr)[4]; //指针所指向的的类型是int*()[4]

    指针的值  指针的值也叫作指针所指向的内存区或地址。指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。

    3、指针运算

    指针的赋值运算

    指针也是一个变量,它自己占据一个4个字节的地址空间(由于程序的寻址空间是2^32次方,即4GB,所以用4个字节表示指针就已经能指向任何程序能够寻址到的空间了,所以指针的大小为4字节),指针的值是另一个东西的地址,这个东西可以是普通变量,结构体,还可以是个函数等等。由于,指针的大小是4字节,所以,我们可以将指针强制转换成int型或者其他类型。同样,我们也可以将任何一个常数转换成int型再赋值给指针。所有的指针所占的空间大小都是4字节,他们只是声明的类型不同,他们的值都是地址指向某个东西,他们对于机器来说没有本质差别,他们之间可以进行强制类型转换。

    C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值。不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个地址就是硬件访问的依据,而名字只是提供给程序员的一种记住这个地址的方便一点的方法。但是,不同的变量在机器中都是0-1代码,所以,我们不能简单的通过检查一个值的位来判断它的类型。  不同类型指针的转换涉及到强制类型转换

    指针 to 指针的强制类型转换是指将指针所指的内容的类型由原先的类型转换为后面的类型。  int a = 1;  int *p = & a;  float * p1 = (float*)p;  则p和p1的值都是&a,但是* p是将&a地址中的值按照int型变量进行解释,而*p1则是将&a地址中的值按照float型变量进行解释。

    //指针类型强制转换: int m; int *pm = &m; char *cp = (char *)&m; //pm指向一个整型,cp指向整型数的第一个字节 12345 12345

    下面的例子说明了指针的步长问题。

    /*指针的移动有个步长,步长等于sizeof(指针指向的元素类型) */ #include<stdio.h> int main(void) { int a[5] = {1, 2, 3, 4, 5}; int *ptr1 = (int*)(&a + 1); //&a(数组指针)指针指向的元素为整个数组,故加为sizeof(数组) int *ptr2 = (int*)((int)a + 1); //a地址再加一个字节,直接地址值相加而不是指针 int *ptr3 = (int*)(a + 1); //a为数组首元素的地址,a+1为数组第二个元素的地址 /* 数组a在内存的存放形式为 *01000000 020000000 03000000 04000000 05000000 *ptr2指向01000000的第二个字节,故*ptr2=00000002 * */ printf("%x %x %x\n", ptr1[-1], *ptr2, *ptr3); return 0; } 12345678910111213 12345678910111213

    赋值运算遇到的三个问题

    NULL(空指针)野指针指针变量的之间的赋值

    (1)NULL指针:NULL 是一个标准规定的宏定义,用来表示空指针常量。

    #define NULL (void *)0 12 12

    空指针在计算机中就是0地址,不容许对0地址做任何操作。  int *p =NULL;更容易使读程序的人意识到这里是一个指针赋值。

    (2)野指针  野指针问题及如何避免

    野指针主要由下面两种原因导致的。

    指针变量没有被初始化。指针变量在定义后如果没有初始化是野指针,其值不为NULL;指针 p 被 free 或者 delete 之后,没有置为 NULL;

    因此,对症下药,在编程过程上遵循如下原则:

    1)凡是定义的指针变量初始化为NULL;

    2)指针 p 被 free 或者 delete 之后将其值赋为NULL;

    野指针:指向不确定地址的指针变量。(即没有初始化)使用野指针易因内存泄露出现段错误。而造成内存泄露的原因有两个:

    访问了没有权限的内存(平时我们正确使用指针的时候,系统应经将相应的内存分配给用户,但是如果指向没有分配的内存,系统会判定我们没有权限)访问了已经释放了的内存。

    因为野指针主要是因为我们平时编程习惯造成的,因此我们只能避免野指针的出现,而不能杜绝。

    在我们在编程时,做到以下几点可以有效地避免野指针的出现。

    第一,当一个指针没有指向时,我们一般默认指向NULL。(NULL代表内存的0地址,并且NULL是不允许做任何操作的)

    第二,使用malloc分配内存。(在堆空间里分配内存)

    #difine MAX_SIZE 1024; char *ptr = (char *) maollc (sizeofchar) * MAX_SIZE); 12 12

    如何避免野指针?  说先应该说养成良好的编码习惯。  1、当指针没有指向时,应该将指针初始化为NULL.  2、检查是否分配空间,如果没有则要分配内存。(分配成功,返回内存的首地址;分配不成功,返回NULL)。  3.检查是否分配成功(若失败,则 exit(1) 退出程序)。  4.初始化内存空间,清空内存中的数据 (malloc分配的空间里可能存在垃圾值,因此我们需要清空,可以用到memset或bzero 函数)。  4.使用内存后,释放内存(free,这时ptr又变成野指针)。  6.free之后将指针再次置为NULL。

    当看到指针指向NULL时:  ①注意不能对指针指向的空间做操作  ②提醒这是一个野指针

    (3)指针变量的之间的赋值  不同指针类型变量赋值导致的问题:  长指针赋值给短指针,数据丢失。(长短指的是步长);  短指针赋值给长指针,数据多取。

    《void * 的概念》  鉴于指针之间这种灵活的强制类型转换的需求和出于简化代码的考虑,ANSI C引入了空指针即void*。void指针又名万能指针,在现在的很多程序中,当参数不确定时就用万能指针代替,这一类的指针在线程\进程函数里特别常见。  ANSI C规定,void指针可以复制给其他任意类型的指针,其他任意类型的指针也可以复制给void指针,他们之间复制不需要强制类型转换。当然任何地址也可以复制给void型指针。

    2、指针的算术运算

    int a[10] = {1,2,3,4,5,6,7,8,9,10}; int *ptr = &a[0]; int *str = &a[5]; printf("%d\n",*(ptr + 1)); printf("%d\n",str - ptr); 123456 123456

    结果:*(ptr + 1)= 2; str- ptr = 5;

    指针之间只有减法,且同时必须同时指向同一个空间。

    转载请注明原文地址: https://ju.6miu.com/read-50330.html

    最新回复(0)