与指针相关的运算符
地址运算符 | 注解 | 示例 |
---|
& | 后跟一个变量名时,&给出该变量的地址 | &address表示address的地址 | * | 后跟一个指针名或地址时,*给出存储在指针指向地址上的值 | *num表示num的值 |
简单变量把值作为基本量,把地址作为通过&运算符的主要用途。更重要的是通过&、和指针可以操纵地址和地址上的内容
指针和数组
数组和指针的关系十分密切,可以使用指针标识数组的元素和获得元素的值。从本质上看,同一个对象有两种表示法。C语言标准在描述数组表示法时的确借助了指针。
ar[n]的意思是 *(ar+n)
可以认为 *(ar+n)的意思是 ”到内存的ar位置 然后移动n个单位“
数组名是数组首元素的地址
int main()
{
int arr[2]={1,2};
printf("%p %p",&arr[2],arr+2);
printf("%d %d",*(arr+2),arr[2]);
}
sum+=*index++;
一元运算符 * 和++的优先级相同,但结合律是从右往左的,所以index++先求值,然后才是*index,
也就是指针index先递增后指向,使用后缀形式(index++)意味着先把指针指向位置上的值加到sum上,然后再递增指针。
如果使用*++index,顺序反过来,先递增指针再使用指针指向位置上的值
如果使用(*index)++,则先获取指针位置上的值再递增该值
const修饰
int arr[4]={1,2,3,4};
**********************第一种情况**********************
const int *p=arr;
*arr=10;
**********************第二种情况**********************
void test_const(const int *p)
**********************第三种情况**********************
int * const p=arr;
**********************第四种情况**********************
const int *const p=arr;
指针与多维数组
int arr[2][3] = { {1,2,3},{4,5,6} };
- 因为数组名arr是数组首元素的地址,所以arr的值和&arr[0]的值一样。而arr本身是一个内含两个整数的数组,所以arr[0]和它首元素(一个整数)的地址(&arr[0][0]的值)相同
arr[0]是一个占有一个int大小对象的地址,而arr是一个占有两个int大小对象的地址。因为这个整数和内含两个整数的数组都开始于同一个地址,所以arr和arr[0]的值相同 - 给指针和地址+1,其值会增加对应类型大小的数值。arr和arr[0]不同,因为arr指向的对象占用了两个int大小,而arr[0]指向的对象只占一个int大小。因此arr+1和arr[0]+1的值不同
- 解引用一个指针(使用*运算符)或在数组名后使用带下标[]运算符,得到引用对象代表的值。因为arr[0]是数组首元素(arr[0][0])的地址,所以 *(arr[0])表示存储在arr[0][0]上的值(1个int类型的值)
int main()
{
int arr[4][2] = { {2,4},{6,8},{1,3},{5,7} };
printf("arr=%p, arr+1=%p \n", arr, arr + 1);
printf("arr[0]=%p, arr[0]+1=%p\n", arr[0], arr[0] + 1);
printf("*arr=%p, *arr+1=%p\n", *arr, *arr + 1);
printf("arr[0][0]=%d\n", arr[0][0]);
printf("**arr=%d\n", **arr);
printf("arr[2][1]=%d\n", arr[2][1]);
printf("*(*(arr+2)+1)=%d", *(*(arr+2)+1));
return 0;
}
理解表达式的思路:
arr | 二维数组首元素地址(每个元素都包含两个int类型的一维数组) |
---|
arr+2 | 二维数组的第3个元素的地址【一维数组】 | *(arr+2) | 二维数组的第3个元素【一维数组】的首元素【1个int类型】地址 | *(arr+2)+1 | 二维数组的第3个元素【一维数组】的第2个元素【1个int类型】地址 | * (*(arr+2)+1) | 二维数组的第3个元素【一维数组】的第2个元素【1个int类型】的值 ==arr[2][1] |
个人理解:对于多维数组而言,*运算符只有精确到1位int类型的时候,才能返回准确的int值。
声明多维数组的的指针
int (*p)[2];
int *p[2];
实例
int main()
{
int arr[4][2] = { {2,4},{6,8},{1,3},{5,7} };
int(*p)[2];
p = arr;
printf("p=%p, p+1=%p\n", p, p + 1);
printf("p[0]=%p, p[0]+1=%p\n", p[0], p[0] + 1);
printf("p[0][0]=%d\n", p[0][0]);
printf("*p[0]=%d\n", *p[0]);
printf("**p=%d\n", **p);
printf("p[2][1]=%d\n", p[2][1]);
printf("*(*p+2)+1=%d", *(*(p + 2) + 1));
return 0;
}
p虽然是一个指针,不是数组名,但是也可以使用数组表示法(p[2][1])。可以使用数组表示法或指针表示法来表示一个数组元素,既可以使用数组名也可以使用指针名
arr[n][m]==*(*(arr+n)+m)
p[n][m]==*(*(p+n)+m)
指针的兼容性
指针之间的赋值比数值之间的赋值要严格,标准规定了非const指针更改const数据是未定义的
int main()
{
const int** p;
int* p1;
const int a = 13;
p = &p1;
*p = &a;
printf("%d\n", **p);
*p1 = 10;
printf("%d", a);
return 0;
}
|