指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
所有指针的值的实际数据类型,不管是整型、浮点型、字符型,还是其他的数据类型,都是一样的,都是一个代表内存地址的长的十六进制数。
定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值,这些是通过使用一元运算符 *来返回位于操作数所指定地址的变量的值。
code:
#include
int main ()
{
int var = 20; /* 实际变量的声明 */
int *ip; /* 指针变量的声明 */
ip = &var; /* 在指针变量中存储 var 的地址 */
printf("Address of var variable: %p\n", &var );
/* 在指针变量中存储的地址 */
printf("Address stored in ip variable: %p\n", ip );
/* 使用指针访问值 */
printf("Value of *ip variable: %d\n", *ip );
return 0;
}
result:
Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。
NULL 指针是一个定义在标准库中的值为零的常量。
code:
#include
int main ()
{
int *p = NULL;
printf("p 的值是 %p\n", p );
return 0;
}
result:
p 的值是 0
如需检查一个空指针,您可以使用 if 语句:
if(p) /* 如果 p 非空,则完成 */
if(!p) /* 如果 p 为空,则完成 */
C指针是一个用数值表示的地址,你可以用对指针进行++ 、 – 、 + 、 - 运算操作。
code:
#include
const int LENGTH = 3;
int main (int argc, const char * argv[]) {
int var[] = {10, 100, 200};
int i, *ptr;
/* 指针中的数组地址 */
ptr = var;
for ( i = 0; i < LENGTH; i++)
{
printf("存储地址:var[%d] = %p\n", i, ptr );
printf("存储值:var[%d] = %d\n", i, *ptr );
/* 移动到下一个位置 */
ptr++;
}
return 0;
}
result:
存储地址:var[0] = 0x7ffeefbff67c
存储值:var[0] = 10
存储地址:var[1] = 0x7ffeefbff680
存储值:var[1] = 100
存储地址:var[2] = 0x7ffeefbff684
存储值:var[2] = 200
CODE:
#include
const int LENGTH = 3;
int main (int argc, const char * argv[]) {
int var[] = {10, 100, 200};
int i, *ptr;
/* 指针中的数组地址 */
ptr = &var[LENGTH - 1];
for ( i = LENGTH; i > 0; i--)
{
printf("存储地址:var[%d] = %p\n", i - 1, ptr );
printf("存储值:var[%d] = %d\n", i - 1, *ptr );
/* 移动到下一个位置 */
ptr--;
}
return 0;
}
RESULT:
存储地址:var[2] = 0x7ffeefbff684
存储值:var[2] = 200
存储地址:var[1] = 0x7ffeefbff680
存储值:var[1] = 100
存储地址:var[0] = 0x7ffeefbff67c
存储值:var[0] = 10
CODE:
#include
const int LENGTH = 3;
int main (int argc, const char * argv[]) {
int var[] = {10, 100, 200};
int i, *ptr;
/* 指针中第一个元素的地址 */
ptr = var;
i = 0;
while ( ptr <= &var[LENGTH - 1] )
{
printf("Address of var[%d] = %p\n", i, ptr );
printf("Value of var[%d] = %d\n", i, *ptr );
/* 指向上一个位置 */
ptr++;
i++;
}
return 0;
}
RESULT:
Address of var[0] = 0x7ffeefbff67c
Value of var[0] = 10
Address of var[1] = 0x7ffeefbff680
Value of var[1] = 100
Address of var[2] = 0x7ffeefbff684
Value of var[2] = 200
int *ptr[LENGTH]
这里将ptr声明为一个数组,由LENGTH个整数指针组成。因此,ptr中的每个元素,都是一个指向int值的指针。
CODE:
#include
const int LENGTH = 3;
int main ()
{
int var[] = {10, 100, 200};
int i, *ptr[LENGTH];
for ( i = 0; i < LENGTH; i++)
{
ptr[i] = &var[i]; /* 赋值为整数的地址 */
}
for ( i = 0; i < LENGTH; i++)
{
printf("Value of var[%d] = %d\n", i, *ptr[i] );
}
return 0;
}
RESULT:
Value of var[0] = 10
Value of var[1] = 100
Value of var[2] = 200
指向指针的指针是一种多级间接寻填的形式,或者说是一个指针链。一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。
int **var;
当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符。
CODE:
#include
int main ()
{
int var;
int *ptr;
int **pptr;
var = 3000;
/* 获取 var 的地址 */
ptr = &var;
/* 使用运算符 & 获取 ptr 的地址 */
pptr = &ptr;
/* 使用 pptr 获取值 */
printf("Value of var = %d\n", var );
printf("Value available at *ptr = %d\n", *ptr );
printf("Value available at **pptr = %d\n", **pptr);
return 0;
}
RESULT:
Value of var = 3000
Value available at *ptr = 3000
Value available at **pptr = 3000
C 语言允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。
CODE:
#include
/* 函数声明 */
double getAverage(int *arr, int size);
int main ()
{
/* 带有 5 个元素的整型数组 */
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
/* 传递一个指向数组的指针作为参数 */
avg = getAverage( balance, 5 ) ;
/* 输出返回值 */
printf("Average value is: %f\n", avg );
return 0;
}
double getAverage(int *arr, int size)
{
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i)
{
sum += arr[i];
}
avg = (double)sum / size;
return avg;
}
RESULT:
Average value is: 214.400000
从函数返回指针,您必须声明一个返回指针的函数。另外,C 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。
CODE:
#include
int * getArray();
int main (int argc, const char * argv[]) {
int *p = getArray();
int i;
for (i = 0; i < 3; i++) {
printf("*(p + [%d]) : %d\n", i, *(p+i));
}
return 0;
}
int * getArray() {
static int array[] = {1, 3, 5};
return array;
}
RESULT:
*(p + [0]) : 1
*(p + [1]) : 3
*(p + [2]) : 5
函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。
CODE:
#include
#include
// 回调函数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
for (size_t i=0; iarray[i] = getNextValue();
}
// 获取随机值
int getNextRandomValue(void)
{
return rand();
}
int main(void)
{
int myarray[10];
populate_array(myarray, 10, getNextRandomValue);
for(int i = 0; i < 10; i++) {
printf("%d ", myarray[i]);
}
printf("\n");
return 0;
}
RESULT:
16807 282475249 1622650073 984943658 1144108930 470211272 101027544 1457850878 1458777923 2007237709
指针的一些复杂说明: