上一篇中介绍了什么是C语言中的指针,以及指针具备哪些基本操作。本篇继续介绍C语言中指针常见的几种用法。
指针的算术运算
指针的加减运算
根据指针变量的定义,易知指针可以进行算术运算,包括加减、递加递减。具体运算规则如下:
- 指针递增,会指向当前地址的下一个存储单元
-
指针递减,会指向当前地址的前一个存储单元
- 递增和递减时改变的字节数取决于指针指向的变量数据类型的长度
- 例如ptr是指向地址1000的int指针,是32位证书。对其执行递加后指向1004,因为int型为4字节
举个例子
1 |
|
上述程序的运行结果为:
1 |
|
指针的比较
指针可以通过关系运算符进行比较,如==、>、<。比较的前提是两个指针指向的是相关的变量,比如都指向int。举个例子
1 |
|
上述代码的执行结果为:
1 |
|
指针数组
数组可以用来存储变量或常量,因此可以用数组来存放指针,即为指针数组。
举个例子,现在有一个整数数组,其中存放的都是整数值,相对数组中的元素访问可以通过数组的索引实现。
1 |
|
通过上述代码,可以逐个打印出数组中的整数元素。
通过指针定义可知,指针可以存储变量的地址值,通过“ * ”运算符可以访问地址对应变量的值。因此,对于数组中的每一个元素,都可以为其声明一个指针变量,指向该数组中的元素。这些指向数组元素的指针可以放在一个数组中存储,这个数组就是指针数组。对以上代码做如下改动,可以得到:
1 |
|
两个代码的执行输出相同,区别在于第二个代码使用了指针数组ptr。
指针在函数中的应用
指针作为一种变量,自然是可以在函数中应用的,包括作为参数传递给函数以及从函数中作为返回值返回。下面对两种情况进行梳理。
传递指针给函数
传递指针给函数时,需要在函数参数部分声明为指针。
举个例子
1 |
|
上述例子中,getSeconds函数中的参数为long型指针。在main函数中调用的是&sec
,因为指针就是地址,所以这个地方的参数是sec变量的地址,也就是指向sec变量的指针。
能接受指针作为参数的函数,也能接受数组作为参数,例如:
1 |
|
getAverage函数的第一个参数为指针,在main函数调用时的参数为balance数组。因为在C语言中已经声明一个数组(int a[2];
)的话,可以用a
表示指向数组的指针,初始指向数组的第一个元素。
从函数返回指针(指针函数)
指针作为一种变量,自然可以从函数中返回,不过需要注意的是不可以返回指向局部变量的指针,除非局部变量声明为static
。因为局部变量是存在栈中的,函数调用结束,栈中的内存地址会被释放,该地址不再存原来的局部变量,无法访问,因此不能返回指向局部变量的指针,而static型的变量是存储在静态数据区的,函数执行结束仍然存在,所以可以返回。
1 |
|
还有一种“特殊”的指针,特殊之处在于其指向的是函数,即指针存储的时函数的首地址。C语言中规定函数名会被转换为指向这个函数的指针,除非这个函数名作为&操作符或者sizeof操作符的操作数。也就是说f = test
中,test函数会被自动转换为&test,f = &test
中因为已经显式地发生了转换,所以不会再自动转换。此外需要注意,指向函数的指针必须初始化或者具有0值才可以使用,且指向函数的指针无法进行自增运算,无法对函数名进行复制,也不能进行算术运算
1 |
|
1 |
|
1 |
|