//---- 1. 字符指针可以在定义时直接赋值
//---- 2. 指针在使用前必须先初始化
//---- 3. 通过分配内存给指针赋值,此时指针指向所分配的内存的首地址。
3.1 申请分配内存后,必须检查是否成功。
3.2 指针释放后应该置NULL
//---- 4. 指针的增减是以指针类型的字节长度为单位进行的
//---- 5. 指针与数组
5.1 如果int array[3][4],那么array就是一个数组指针,其类型长度为3*4*sizeof(int)=48
5.2 数组指针 : int (*arp)[4] 定义了一个数组指针,arp指向一个含4个int元素的一维数组。
5.3 指针数组 : int *par[4] 定义了一个有4个元素的指针数组, 每个元素是一个整型类指针。
//---- 6.指针的指针
6.1 多重指针定义和赋值
6.2 通过分配内存给多重指针赋值
6.3 释放多重指针所指内存 : 指针释放后应该置NULL
pointer.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i,j,k;
int m;
//---- 1. 字符指针可以在定义时直接赋值
printf("\n\n ----- 1. Char Pointer Initilization -----\n");
char *pc = "hello world!"; //OK
printf( "char pointer pc = %s\n", pc);
int *p = 5; // WRONG !!! warning: initialization makes pointer from integer without a cast !!!!
printf( " p = %p \n", p); // p = 0x5
//---- 2. 指针在使用前必须先初始化
printf("\n\n ----- 2. Pointer before Init is (nil) -----\n");
int *pa;
printf(" int *pa; pointer before init: pa = %p, or the value of pa is %x\n",pa,(unsigned int)pa);
// *pa = 1; // WRONG!!! Segmentation fault (core dumped) !!!
//---- 3. 通过分配内存给指针赋值,此时指针指向所分配的内存的首地址。
printf("\n\n ----- 3. Pointer and Malloc/Free -----\n");
pa=(int *)malloc(5*sizeof(int));
printf("after malloc 5*sizeof(int), pointer values: \n");
// --- 3.1 申请分配内存后,必须检查是否成功。
for(i=0;i<5;i++)
printf("pa[%d]=%d \n",i,pa[i]);
printf("pa[6] is out of range, however: ");
printf("pa[6]=%d \n",pa[6]);
free(pa);
//---- 4. 指针的增减是以指针类型的字节长度为单位进行的
printf("\n\n ----- 4. Pointer Type Size -----\n");
for(i=0;i<5;i++) {
printf("pa+%d=%p\n",i,pa+i);
}
/* -- print result,4bytes for sizeof(int) ----
pa+0=0x201b420
pa+1=0x201b424
pa+2=0x201b428
pa+3=0x201b42c
pa+4=0x201b430
*/
//---- 5. 指针与数组
printf("\n\n ----- 5. Array and Pointer -----\n");
int array[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
for(i=0;i<3;i++)
for(j=0;j<4;j++)
printf("array[%d][%d]=%d\n",i,j,array[i][j]);
int *parray=array; //!!!! warning: initialization from incompatible pointer type !!!!
printf("\nint array[3][4]=...;\n\nint *parray=array; \n");
printf("WARNING: initialization from incompatible pointer type!!!\n");
//------5.1 如果int array[3][4],那么array就是一个数组指针,其类型长度为3*4*sizeof(int)=48
printf("!!! sizeof(array)=%ld while sizeof(*parray)=%ld \n\n",sizeof(array),sizeof(*parray));
parray=(int *)array;
printf("parray=(int *)array;\n");
printf("parray[9]=%d = array[2][1]=%d \n", parray[9], array[2][1]);
//------5.2 数组指针 : int (*arp)[4] 定义了一个数组指针,arp指向一个含4个int元素的一维数组。
printf("\n\n ----- 5.1 Array Pointer: int (*arp)[] [ > ( > * -----\n");
int (*arp)[4];
arp=array; //或 ap= array[0] 或 ap=&array[0][0];
for(i=0;i<4;i++)
{
printf("(arp+1)[0][%d]=%d\n",i,(arp+1)[0][i]);
// arp[2][i] 和 (arp+2)[0][i] 相同!
printf("arp[2][%d]=%d ",i,arp[2][i]);
printf("(arp+2)[0][%d]=%d\n",i,(arp+2)[0][i]);
}
//------5.3 指针数组 : int *par[4] 定义了一个有4个元素的指针数组, 每个元素是一个整型类指针。
printf("\n\n ----- 5.2 Pointer Array: int *par[] [ > ( > * -----\n");
int *par[3];
par[0]=(int *)array[0]; //或则 &array[0][0]
par[1]=(int *)array[1];
par[2]=(int *)array[2];
for(i=0;i<3;i++)
{
printf("par[%d]=(int *)array[%d]; ",i,i);
printf(" *par[%d] = %d \n", i,*array[i]); //*array[i] 和 array[i][0] 相等*/
}
//----- 6.指针的指针
printf("\n\n ----- 6. Pointer to Pointer -----\n");
//-------6.1 多重指针定义和赋值
int var=666;
int *ptr;
int **pptr;
printf("\n\n ----- 6.2 Pointer to Pointer: Assignment -----\n");
printf("var=%d\n",var);
// pptr=&(&var); // !!! WRONG !!! & must follows with a variable name.
ptr=&var;
printf("ptr=&var=%p\n",ptr);
pptr=&ptr;
printf("pptr=&ptr=%p\n",pptr);
printf("\npptr[0] = %p\n", pptr[0]);
printf("pptr[0][0] = %d\n", pptr[0][0]);
//-------6.2 通过分配内存给多重指针赋值
printf("\n\n ----- 6.2 Pointer to Pointer: Malloc and Free -----\n");
int *** ppptr; //[3][2][2]
// ppptr ----> (int **) ----> (int *) ----> (int)
// | | |
// | | |--> (int)
// | |-> (int *)
// |
// |--> (int **) --
// |
// |--> (int **) --
for(m=0;m<50000;m++) //------------- check memory leakage ----------
{
//----- malloc for ppptr : pointer to (int **)
ppptr=malloc(3*sizeof(int **));
printf("ppptr=malloc(3*sizeof(int **))=%p\n", ppptr);
for(i=0;i<3;i++) {
//----- malloc for (* ppptr) : pointer to (int *)
ppptr[i]=malloc(2*sizeof(int *));
printf("*ppptr: ppptr[%d]=%p \n",i,ppptr[i]);
for(j=0;j<2;j++) {
//----- malloc for (** ppptr) : pointer to (int)
ppptr[i][j]=malloc(2*sizeof(int));
printf("**ppptr: ppptr[%d][%d]=%p \n",i,j,ppptr[i][j]);
}
}
ppptr[2][1][0]=88888;
printf("ppptr[2][1][0]=88888 \n");
for(i=0;i<3;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
printf("***ppptr: ppptr[%d][%d][%d]=%d \n",i,j,k,ppptr[i][j][k]);
//} //---END test leakage
//-------6.3 释放多重指针所指内存 : 指针释放后应该置NULL
printf("\n\n ----- 6.3 Free Pointer to Pointer -----\n");
for(i=0;i<3;i++) {
for(j=0;j<2;j++) {
free(ppptr[i][j]); //---free: ppptr[i][j]=malloc(2*sizeof(int));
ppptr[i][j]=NULL;
//printf("ppptr[%d][%d][0] = %d\n",i,j,ppptr[i][j][0]);
printf("ppptr[%d][%d] = %p\n",i,j,ppptr[i][j]);
if(j == 2-1){
free(ppptr[i]); //---free: ppptr[i]=malloc(2*sizeof(int *));
ppptr[i]=NULL;
printf("ppptr[%d] = %p\n",i,ppptr[i]);
}
}
}
free(ppptr); //---free: ppptr=malloc(3*sizeof(int **));
ppptr=NULL;
printf("ppptr = %p\n",ppptr);
} //---END check leakage
return 0;
}
/*
--- mem result ---
----- 6.2 Pointer to Pointer and Malloc/Free -----
ppptr=malloc(3*sizeof(int **))=0xaec420
*ppptr: ppptr[0]=0xaec440
**ppptr: ppptr[0][0]=0xaec460
**ppptr: ppptr[0][1]=0xaec480
*ppptr: ppptr[1]=0xaec4a0
**ppptr: ppptr[1][0]=0xaec4c0
**ppptr: ppptr[1][1]=0xaec4e0
*ppptr: ppptr[2]=0xaec500
**ppptr: ppptr[2][0]=0xaec520
**ppptr: ppptr[2][1]=0xaec540
--- proc maps ---
00400000-00402000 r-xp 00000000 08:07 139229 /home/midas-zhou/pointer
00601000-00602000 r--p 00001000 08:07 139229 /home/midas-zhou/pointer
00602000-00603000 rw-p 00002000 08:07 139229 /home/midas-zhou/pointer
00aec000-00b0d000 rw-p 00000000 00:00 0 <<<-------- [heap]
7fa6e50d3000-7fa6e5293000 r-xp 00000000 08:08 792498 /lib/x86_64-linux-gnu/libc-2.23.so
7fa6e5293000-7fa6e5493000 ---p 001c0000 08:08 792498 /lib/x86_64-linux-gnu/libc-2.23.so
7fa6e5493000-7fa6e5497000 r--p 001c0000 08:08 792498 /lib/x86_64-linux-gnu/libc-2.23.so
7fa6e5497000-7fa6e5499000 rw-p 001c4000 08:08 792498 /lib/x86_64-linux-gnu/libc-2.23.so
7fa6e5499000-7fa6e549d000 rw-p 00000000 00:00 0
7fa6e549d000-7fa6e54c3000 r-xp 00000000 08:08 792470 /lib/x86_64-linux-gnu/ld-2.23.so
7fa6e56a3000-7fa6e56a6000 rw-p 00000000 00:00 0
7fa6e56c2000-7fa6e56c3000 r--p 00025000 08:08 792470 /lib/x86_64-linux-gnu/ld-2.23.so
7fa6e56c3000-7fa6e56c4000 rw-p 00026000 08:08 792470 /lib/x86_64-linux-gnu/ld-2.23.so
7fa6e56c4000-7fa6e56c5000 rw-p 00000000 00:00 0
7ffc0fc00000-7ffc0fc21000 rw-p 00000000 00:00 0 [stack]
7ffc0fd7a000-7ffc0fd7d000 r--p 00000000 00:00 0 [vvar]
7ffc0fd7d000-7ffc0fd7f000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
--- Leakage Test ----
VIRT: virtual memory
RES: physical memory
( top -d 1 )
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
29063 midas-z+ 20 0 4356 728 660 R 39.2 0.0 0:07.99 pointer
*/