首页 > 其他 > 详细

C指针笔记

时间:2020-04-07 09:12:23      阅读:64      评论:0      收藏:0      [点我收藏+]

指针


指针类型

XX类型 +  *  →XX指针类型

int *   整形指针类型

char *  字符型指针类型

 

指针变量

用指针类型声明的变量就是指针变量

int  a;//声明了一个整形变量

int* a;//声明了一个整形指针变量

 

指针变量赋值

指针变量存放的是变量的内存地址,赋值原则:什么类型的指针变量,就应该赋予相应类型变量的地址值:

① int* p = 0x40003a04 ; //不易解读

② int  a ;  char b = ‘B’ ;  int *p1 = &a ;  char *p2 = &b ;

 

内存地址

内存指RAM中的特定位置,通常以十六进制的数字表示,如0x40003a04;

32位cpu中,地址是一个32位的无符号整形数,可以表示2^32(4GB)的地址。

 

指针的本质

不论什么类型的指针,存放的一定是地址,指向相应变量的地址,而地址值就是一个32位无符号的整数,所以任何指针类型的大小都是4字节;

指针类型 → unsigned int

 

常见的指针类型

类型

int

char

float

double

struct A{int a;int b;}

void func()

指针类型

int*

char*

float*

double*

struct A*

typedef void(*pFunc)()

 

定义指针并初始化

int* p1 = NULL ;

char* p1 = NULL ;

float* p1 = NULL ;

double* p1 = NULL ;

 

指针变量赋值

int a = 5 ;  int* p1 = &a ;

 

获取指针变量所指变量的值

利用*获取指针所指变量的值

printf ( “%d” , *p1) ;

 

*的两种用法

类型*

指针类型

*指针变量

取指针所指变量的值

 

结构体类型的指针类型

类型

struct A{int a;int b;}

指针类型

struct A*

定义结构体指针变量

struct A* p = NULL ;

获取结构体变量的地址

struct  A  {int a;int b;};

struct  A  a ;

printf ( “%p” , &a) ;

 

利用*获取结构体指针所指的变量值

struct  A  { int a ; int b ; } ;

struct  A  a = { 5 , 6 } ;

struct  A* p = &a ;

printf ( “%d , %d” , (*p).a , (*p).b ) ;

利用指针变量访问结构体成员

->引用结构体成员变量

struct  A  { int a ; int b ; } ;

struct  A  a = { 5 , 6 } ;

struct  A* p = &a ;

printf ( “%d , %d” , p->a , p->b ) ;

 

 

函数指针:指针标志*在函数名前

函数:void func( ){ printf ( “func\n” ); }

 

函数的地址

对于函数而言,函数名就是其首地址:下述两个取到的地址相同:

printf ( “%p\n” , func );

printf ( “%p\n” , &func);

 

函数指针类型,不加typedef表示定义了一个函数指针变量

函数原型

void func()

指针类型

typedef void(*pFunc)()

 

函数指针的赋值

pFunc  p = func ;pFunc  p = &func ;

利用函数指针变量调用函数

pFunc  p = func ;

p() ; //调用func函数

 

复杂的函数指针

int ( * (* p )( int ) )( int );

eg. typedef int( * (* pFunc3 )( int ) )( int );

pFunc3  func3 = func;

 

野指针

一个指向非法内存区域的指针

指向已经被销毁的内存

指向无权访问的内存

①int* p = (int* )malloc( int ) ;

free(p) ; //此时的p已经变为了野指针,再取该地址的值时,是乱码

随机将p指向一块未知的不确定的内存区域;将会导致内存被修改,引起不易察觉的BUG或系统崩溃

 

避免野指针

对申请的指针进行初始化:int* p = NULL

释放内存后将指针置为NULLfree(p) ;  p = NULL;

 

指针的运算:加法/减法

指针的加法:指针+N:表示将指针的值加上N*sizeof(类型)个字节

int  int  int  int

↑     ↑

int*p   p+3

指针的加法:++指针:表示将指针的值加上sizeof(类型)个字节,运行后指针p的值改变

int   int  int  int

 ↑   ↑

int*p ++p

指针的法:指针-N:表示将指针的值减去N*sizeof(类型)个字节

int  int  int  int

↑     ↑

p-3     int*p

指针的法:--指针:表示将指针的值减去sizeof(类型)个字节,运行后指针p的值改变

int   int  int  int

↑     ↑

--p int*p

 

指针-指针:表示将两个地址值相减得到的字节数:p2-p1=3

int  int  int  int

↑  ↑

int*p1 int*p2

 

一维数组

int a[5] = {1,2,3,4,5};占用一个连续的内存空间,数组中的每个值占一个字节;

一维数组的首地址是数组名或第一个元素的地址;

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

int*p = a ;

int*p = &a[0] ;

 

指针与数组名的区别

类型

是否可变

可运算

数组名

不可变,它是常量

无法++--

指针

可以变,它是变量

可以++--

 

利用指针访问数组元素

for( int i = 0 ; i < 5 ; i++ )

{

printf(“%d\n” , *(p+i));

}

 

for( int i = 0 ; i < 5 ; i++ )

{

printf(“%d\n” , *(p++));

}

 

for( int i = 0 ; i < 5 ; i++ )

{

printf(“%d\n” , *(a+i));//数组名是一个常量,不可改变,通过加i偏移取值,不能自加减

}

 

二维数组

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

a[0]1 2 3

a[1]4 5 6

二维数组的首地址是数组名或第一个元素的地址;

 

二维数组指针定义

指向二维数组的指针:行指针→类型(*p)[N]

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

int (*p)[3] ;

p = a ;//赋值为数组名

p = &a[0] ;//指向第一个元素的首地址

 

利用指针访问二维数组元素

for( int i = 0 ; i < 2 ; i++ )

for( int j = 0 ; j < 3 ; j++ )

{  printf(“%d\n” , p[i][j] );  }

 

for( int i = 0 ; i < 2 ; i++ )

for( int j = 0 ; j < 3 ; j++ )

{  printf( “%d\n” , *(p[i]+j) );  }//p[i]代表行指针,把p[i]看做一个数组名

 

for( int i = 0 ; i < 2 ; i++ )

for( int j = 0 ; j < 3 ; j++ )

{  printf( “%d\n” , *(*(p+i)+j) );  }

 

a[m][n]等价写法

类型

指针定义

赋值

行指针

int(*p)[N]

a      &a[N]

普通指针

int*

a[N]  &a[M][N]

 

字符串常量本身就是一个地址

hello在内存中存放为h e l l o \0

字符串常量实质就是一段内存,首地址来标识,且字符串常量的值不能改变

 

字符串指针

char* p = “hello”; 不能使用p[1] = ‘a’;来改变内容

给指针变量赋予字符串常量的首地址;

for( int i = 0 ; i < 5 ; i++ )

{ printf( “%c\n” , p[i] );  }

 

for( int i = 0 ; i < 5 ; i++ )

{ printf( “%c\n” , *(p+i) );  }

 

for( int i = 0 ; i < 5 ; i++ )

{ printf( “%c\n” , *(p++) );  }

 

指针的指针

指针变量也占用内存,所以也有内存地址

指针类型:

XX类型   * XX指针类型

XX类型*    XX指针类型   //指针类型

int **   //整形指针的指针类型

char **  //字符形指针的指针类型

float **  //浮点形指针的指针类型

eg.

int a = 10;

int* p = &a;

int** p = &p;

 

利用void传参数

void*可以传递任何类型的地址

void func(void *p)

{//p转换为真实类型}

 

指针变量的强制转换

int a =5 ;

int *p = &a;

int c = (int)p;

int *p2 = (int*) c;

 

指针变量的强制转换

char buf[256]

int* p = (int*) buf ;

*p = 123;

printf( “%d\n” , *p);

 

char buf[256]

struct A{int a;int b;};

A* p = (A*) buf ;

p->a = 12;

p->b = 34;

printf( “%d,%d\n” , p->a , p->b);

 

C指针笔记

原文:https://www.cnblogs.com/ren-hang/p/12644182.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!