Summary
1)数组是一段间断的内存空间
,数组的元素个数为 #define DIM(a) (sizeof(a) / sizeof(*a))
2)指针是一种非凡的变量
,与整数的运算规定为
:p + n; <--> (unsigned int)p + n * sizeof(*p)
当指针p指向一个数组里的元素时,p + 1将指向以后元素的下一元素
;p - 1将指向以后元素的上一元素
。
3)指针之间只反对减法运算
;参加减法运算的指针必须类型雷同
:
留神:只有当2个指针指向同一个数组中的元素时,指针相减才有意义
,意义为指针所指元素的下标差
;当2个指针指向的元素不在同一个数组时
,未定义
。p1 - p2; <--> ((unsigned int)p1 - (unsigned int)p2) / sizeof(type);
4)char* pEnd = s + DIM(s); pEnd指向了数组s中最初一个元素的后一地位
,尽管这个地位不属于数组,但在C语言中,依然认为这个边界地位是属于数组的
,这个知识点在STL中也有利用。
5)指针也能够进行关系运算
(<, <=, >, >=),但前提是同时指向同一个数组中的元素
;
两个指针间能够进行比拟运算
(==,!=),但两个指针的类型必须雷同
;
6)for (p = pBegin; p < pEnd
; p++) ,p指向了数组的首元素,pEnd在C语言中被认为是数组的元素,所以p和pEnd都指向了同一个数组里的元素,类型雷同,可能进行比拟
。
指针和数组剖析
数组是一段间断的内存空间
数组的空间大小为 sizeof(arr_type) * arr_size
数组名可看做指向数组第一个元素的指针常量
1、指针的运算
问题:对于数组int a[5],a + 1的意义是什么?后果是什么?指针运算的意义是什么,后果又是什么?
论断:
指针是一种非凡的变量
,与整数的运算规定为
:p + n; <--> (unsigned int)p + n * sizeof(*p)
当指针p指向一个数组里的元素时,p + 1将指向以后元素的下一元素
;p - 1将指向以后元素的上一元素
。
#include <stdio.h>int main(){ int a[5] = {0}; int* p = NULL; printf("a = 0x%X\n", (unsigned int)(a)); printf("a = 0x%X\n", (unsigned int)(a + 1)); printf("p = 0x%X\n", (unsigned int)(p)); printf("p = 0x%X\n", (unsigned int)(p + 1)); return 0;}输入:a = 0xBFCEEF78a = 0xBFCEEF7Cp = 0x0p = 0x4
指针之间只反对减法运算
;参加减法运算的指针必须类型雷同
:p1 - p2; <--> ((unsigned int)p1 - (unsigned int)p2) / sizeof(type);
留神:只有当2个指针指向同一个数组中的元素时,指针相减才有意义
,意义为指针所指元素的下标差
;当2个指针指向的元素不在同一个数组时
,未定义
#include <stdio.h>int main(){ char s1[] = {'H', 'e', 'l', 'l', 'o'}; char s2[] = {'H', 'e', 'l', 'l', 'o'}; char* p0 = s1; char* p1 = &s1[3]; char* p2 = s2; int i = 0; int* p = &i; printf("%d\n", p0 - p1); // 下标差:-3 printf("%d\n", p0 + p2); // error printf("%d\n", p0 - p2); // undefined behavior printf("%d\n", p0 - p); // error printf("%d\n", p0 * p2); // error printf("%d\n", p0 / p1); // error return 0;}输入:(指针之间的+ * / 都不容许,不同类型指针的减法运算也不容许)test.c:17: error: invalid operands to binary + (have ‘char *’ and ‘char *’)test.c:19: error: invalid operands to binary - (have ‘char *’ and ‘int *’)test.c:20: error: invalid operands to binary * (have ‘char *’ and ‘char *’)test.c:21: error: invalid operands to binary / (have ‘char *’ and ‘char *’)p0 - p2的输入为5,但并不知道这是什么意思
#include <stdio.h>// 计算数组的大小#define DIM(a) (sizeof(a) / sizeof(*a)) int main(){ int s1[] = {'H', 'e', 'l', 'l', 'o'}; int s2[] = {'H', 'e', 'l', 'l', 'o'}; int* p0 = s1; int* p1 = &s1[3]; printf("p1 - p0 = %d\n\n", p1 - p0); // 3 char s[] = {'H', 'e', 'l', 'l', 'o'}; char* pBegin = s; char* pEnd = s + DIM(s); char* p = NULL; printf("pBegin = %p\n", pBegin); printf("pEnd = %p\n", pEnd); printf("Size: %d\n", pEnd - pBegin); // 5 for (p = pBegin; p < pEnd; p++) // 指针比拟,指针运算 { printf("%C", *p); } printf("\n"); return 0;}输入:p1 - p0 = 3pBegin = 0xbf9ff2a7pEnd = 0xbf9ff2acSize: 5Hello
剖析:
- char* pEnd = s + DIM(s); pEnd指向了
数组s中最初一个元素的后一地位
,尽管这个地位不属于数组,但在C语言中,依然认为这个边界地位是属于数组的
,这个知识点在STL中也有利用。 - for (p = pBegin; p < pEnd; p++) ,p指向了数组的首元素,pEnd在C语言中被认为是数组的元素,所以
p和pEnd都指向了同一个数组里的元素,类型雷同,可能进行比拟
。
2、指针的比拟
指针也能够进行关系运算
(<, <=, >, >=),但前提是同时指向同一个数组中的元素
;
两个指针间能够进行比拟运算
(==,!=),但两个指针的类型必须雷同
;
#include <stdio.h> int main(){ int a[5] = {0}; int* p0 = a; int* p1 = &a[1]; char* p2; printf("%d\n", p1 < p0); // ok, 0 printf("%d\n", p1 < p2); // undefined printf("%d\n", p1 != p0); // ok, 1 printf("%d\n", p1 == p2); // undefined return 0;}
以上代码在编译时曾经warning:
test.c:14: warning: comparison of distinct pointer types lacks a cast
test.c:17: warning: comparison of distinct pointer types lacks a cast
本文总结自“狄泰软件学院”唐佐林老师《C语言进阶课程》。
如有错漏之处,恳请斧正。