c语言之浅谈指针(1)

目录

1.引言:

2.字符指针

3.指针数组

 4.数组指针

5.arr 和 &arr的区别

6.数组指针的使用

7.数组和指针传参

 8.函数指针

9.函数指针数组

 10.指向函数指针数组的指针


1.引言:

1).我们都知道指针是个变量,是用来存放地址的,而地址也形象的指向一个空间,因此地址               也被形象的称作指针。

  2).指针在32位平台大小是4个字节,64位是8个字节。

  3).指针也有自己的类型,指针的类型决定了我们用指针访问地址的时候看待的视角,因此                   指针的类型决定了指针向前或者向后走一步有多大(距离)。

 c语言之浅谈指针(1)_第1张图片            

 其中char*类型的指针pc+1跳过一个字节,int*类型的指针pi+1跳过4个字节。

2.字符指针

 字符指针有两种使用的场景:

(1)指向字符

#include 
int main()
{    
char ch = 'w';    
char *pc = &ch;//取出w的地址放到pc指针中
*pc = 'w';   
 return 0;
}

 (2)指向字符串

#include 
int main()
{    
char* pstr = "hello bit.";//这里实际上是把字符串的首字符h的地址放到了指针pstr中   
 printf("%s\n", pstr);   
 return 0;
}

其中hello bit是常量字符串,放在内存中的常量区。因为常量字符串是连续存储的,所以指针通过找到h,就可以找到剩下的字符串。

下面我们来看一道笔试题:

#includ 
int main()
{
	char str1[] = "hello bit."; 
	char str2[] = "hello bit."; 
	char *str3 = "hello bit.";
	char *str4 = "hello bit.";
	if(str1 ==str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");
    if(str3 ==str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");
	return 0;
}

因为str1和str2是两段完全独立的空间,因此存储两个数组的地址是完全不一样的。

但str3和str4都是常量字符串,存储在常量区中,不能被修改。因此相同的指针指向两个字符串。

 通过编译器,结果也确实如此。

3.指针数组

顾名思义指针数组就是一个存放指针的数组。

比如:char *arr1[ ]是存放字符指针的数组

           int *arr2[ ]是存放整型指针的数组

代码1

#include 
int main()
{
    int a = 1;
	int b = 2;
	int c = 3;
	int d = 4;
	int *arr2[] = { &a, &b, &c, &d };//arr2就是一个整形指针数组
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		printf("%d ",*(arr2[i]));
	}
	return 0;
}

代码2

c语言之浅谈指针(1)_第2张图片

 4.数组指针

与指针数组不同,数组指针是一个指针,即指向数组的指针。

跟整形指针和字符指针类似,数组指针是存储数组的地址的指针。

如:int (*parr)[10]= & arr;取出的是数组的地址放到指针中去

*表示parr是指针变量

向外看指针指向了一个数组[10],数组中有10个元素,每个元素类型为int.

int *arr=4; 去掉arr即表示指针类型是int

int (*arr) [ 10 ] ={ 0 }  去掉arr表示指针类型是int(*)[10],此处必须加(),因为[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

5.arr 和 &arr的区别

#include 
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr);
	printf("arr+1 = %p\n", arr + 1);//arr表示数组首元素地址,+1表示跳过一个元素,即4个字节
	printf("&arr+1= %p\n", &arr + 1);//&arr表示整个数组的地址,+1表示跳过整个数组的地址,即40个字节
	return 0;
}

6.数组指针的使用

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

int  (*p)[5]=&arr;将一个数组的地址放到数组指针里面,但这种用法很少。

我们来举一个数组指针在二维数组传参的用法

c语言之浅谈指针(1)_第3张图片

 学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:

int arr[5]  整型数组:一个类型为int类型的整型数组

int *parr1[10] 整形指针数组:parr1是个数组,有10个元素,每个元素都是int *类型,所以parr1是个存放指针的数组。

int (*parr2)[10] 数组指针:*说明parr2是个数组指针

                                           向外看,parr2指向数组,数组有10个元素,每个元素都是int 类型

int (*parr3[10])[5]:数组指针的指针数组:parr3是个数组,数组中有10个元素,每个元素都是一个数组指针。该指针指向的数组有5个元素,每个元素都是int类型。

c语言之浅谈指针(1)_第4张图片

7.数组和指针传参

(1)一维数组传参

c语言之浅谈指针(1)_第5张图片

(2)二维数组的传参

c语言之浅谈指针(1)_第6张图片 

 

 

 (3)一级指针传参

c语言之浅谈指针(1)_第7张图片

 同理二级指针传参时,可以传二级指针变量pn或者&pn,可以用二级指针int **p或者其他类型的二级指针来接收.

c语言之浅谈指针(1)_第8张图片

 8.函数指针

顾名思义函数指针就是保存函数地址的指针

c语言之浅谈指针(1)_第9张图片

 话不多说,我们直接上代码

c语言之浅谈指针(1)_第10张图片

 那么我们来看个例子:

//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);

 代码1表示将0先强制类型转换为void(*)()的函数地址

再对其解引用,就是调用0地址处的函数,而且被调用的函数是无参数的,没有返回值的

代码2

signal是函数名,signal函数有两个参数,第一个是int,第二个是void(*)(int)的函数指针类型。

去掉signal(int , void(*)(int)),整体函数类型是void(*)(int)的函数指针类型

9.函数指针数组

顾名思义就是存放函数指针的数组

  前面我们说了函数的地址可以放到函数指针里面,那么我们为什么还要创建函数指针数组呢?这是因为在一个大型工程里面,我们不可能每遇到一个函数的地址,都来创建一个函数指针,因此需要创建函数指针数组来存放多数的函数的地址。

代码:

c语言之浅谈指针(1)_第11张图片                                                                

 10.指向函数指针数组的指针

顾名思义,指向函数指针数组的指针就是一个指针,指针指向一个数组,数组的元素都是函数指针。

int arr1[10]={0};

int (*parr1)[10]= &arr1;     parr1就是指向整型指针数组的指针

int arr2[10]={0};

int *(*parr2)[10]=&arr2;     parr2就是指向整型指针数组的指针

c语言之浅谈指针(1)_第12张图片

 好啦,指针就简单介绍到这,剩下的我会后面一一介绍。

你可能感兴趣的:(C语言专栏,c语言,c#)