1. 指针
int number = 5;
这条语句会分配一块内存来存储一个整数,使用 number 名称可以访问这个整数。
值5存储在这个区域中。
计算机用一个地址引用这个区域。
在源程序中,这个变量名是不变的,但地址在不同的系统上是不同的。
可以存储地址的变量称为 指针(pointers).存储在指针中的地址通常是另一个变量。
必须要指定指针变量的类型。否则编译器不知道如何处理它所指的内存的内容。
一般给定类型的指针写作 type*, 其中type是任意给定的类型。
类型名void表示没有指定类型。所以void*类型的指针可以包含任意类型的数据项地址。
void*常用做参数类型。
任意类型的指针可以传送为void*类型的值,在使用它时,再将其转换为合适的类型。
指针的命名:最好将p作为指针名的第一个字母。
2. 声明指针
int *pointer;
声明指向int 类型变量的指针,
pointer变量的类型为 int *, 可以存储任意int类型的变量的地址。
这条语句没有进行初始化, 未初始化的指针是非常危险的,所以应总在声明指针时初始化它。
int *pointer = NULL;
NULL是标准库中定义的一个常量,对于指针它表示0。
NULL是不指向任何内存位置的值。这样不会意外覆盖内存。
int number = 10;
int *pointer = &number;
使用&寻址运算符初始化指针变量。 pointer的初值就是number变量的地址。
3. 使用指针
使用*间接运算符可以访问指针所指的变量值, 这个运算符也称为取消引用运算符(dereferencing operator).
#include <stdio.h>
int main(void){
int number = 0;
int *pointer = NULL;
number = 10;
printf("number's address: %p\n", &number);
printf("number's value: %d\n", number);
pointer = &number;
printf("pointer's address: %p\n", &pointer);
printf("pointer's size: %lu\n", sizeof(pointer));
printf("ponter's value: %p\n", pointer);
printf("*ponter's value: %d\n", *pointer);
return 0;
}
//运算结果
$ ./a.out
number's address: 0x7fff5971cc08
number's value: 10
pointer's address: 0x7fff5971cc00
pointer's size: 8
ponter's value: 0x7fff5971cc08
*ponter's value: 10
*pointer 表示存储在pointer中的地址的值。这儿就是存储在number中的值10.
*pointer += 15;
*表示访问pointer变量所指向的内容, 这儿是 number变量的内容, 运行结果为 25;
pointer = &new_number;
改变了pointer指向的变量。
可以用一个指针变量改变多个变量的值, 只要它们的类型与指针相同。
scanf()输入数值时, 使用&运算符获取传给函数的地址。
有指针后,可以用这个指针名字作为参数。
int value = 0;
int *pvalue = &value;
scan(" %d", pvalue);
4. 常量指针
long value = 999L;
const long *pvalue = &value;
使用const, 该指针指向的值不能改变。
如果 *pvalue = 888L; 这样将会编译报错。
value本身的值可以改变, value = 777L; 改变了pvalue指向的值, 但是不用使用pvalue改变。
指针本身不是常量, 所以可以改变它的指向
long number = 888L;
pvalue = &number;
可以使指针中存储的地址不能改变
int count = 43;
int *const pcount = &count;
如果试图改变pcount的指向, pcount = &new_count; 这样将会报错。
但是可以改变pcount指向的值。*pcount = 345; 这样是可以的。
如果都不想让改变, 可以创建一个常量指针,指向一个常量值。
int item = 25;
const int *const pitem = &item;
这样不能改变存储在pitem中的地址, 也不能改变pitem指向的内容。