前些日子,通过一个错误,让我重新理解了指针等。
一、案例:
void
myPrintf_pp
(
int
**
pp
,
int
len
)
{
for
(
int
i
= 0;
i
<
len
;
i
++)
{
printf
(
"第%d个数是%d\n"
,
i
,
*
pp
[
i
]);
}
}
void
myPrintf_p
(
int
**
pp
,
int
len
)
{
for
(
int
i
= 0;
i
<
len
;
i
++)
{
printf
(
"第%d个数是%d\n"
,
i
,
(*
pp
)[
i
]);
}
}
//myPrintf_pp
1.传来的是int *pArray[5],pp[i]是pArray数组每个元素的内容,它们都是个指针,它们存的地址是任意的,可以连续,也可以不连续,
因为里面存的是指针,所以
再取内容才能得到里面的整数,即*pp[i];
//myPrintf_p
1.传来的是int *pArray[5],(*pp)是pArray数组第一个元素的内容(就是第一个元素存的地址),它是个指针,它们存的地址是任意的,可以连续,也可以不连续
因为里面存的是指针,所以要得到pArray数组第一个元素内容里存的整数,需要再解引用才能得到里面的整数,即(*pp)[0];
//存的地址连续:
(*pp)[1]是需要的整数;
//存的地址不连续:
(*pp)[1]是乱码;因为此时的(*pp)[1]是pArray数组第一个元素里存的地址紧接着的后面的地址;
因为(*pp)就是第一个元素存的地址,对它解引用*((*pp)+i)就是取它后面的地址里的内容;
二、案例:
int myArray[4][5] = { {1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15}, {16,17,18,19,20} };
myArray[i] = *(myArray + i)第i行第0列地址
myArray[i] + j = *(myArray + i) + j 第i行第j列地址;
*(myArray[i] + j) = *(*(myArray + i) + j) 第i行第j列元素;
printf("%d ", *(myArray + 1)[1]); //11 第2行第0个元素11(第0 1 2 3行)
printf("%d ", (*(myArray + 1))[1]); //7 第1行第1个元素 7
int arr[2][3] =
{
{1,2,3},
{4,5,6},
};
printf("%d", *(arr[0] + 5)); 打印的是6
int *pArr[2][3] =
{
{1,2,3},
{4,5,6},
};
printf("%d", *(pArr[0] + 5)); 打印的还是6
结论: 1.
myArray
一个指向
int
myarray[5]
的数组指针,,,所以步长是一维数组的大小;
所以myArray相当于是一个数组指针,相当于二级指针;如果myArray只有一行,基本就是一样的了吧;
int (*p)[5] = myArray;
2. int *Array[2][3];这是一个二维数组,每个元素里存储的都是int*变量;若想取其中的元素
就要这样操作*(*(Array[i] + j)) = *(*(*(myArray + i) + j));
3.int *pArray[5];这是一个一维数组,仅仅是因为每个元素里存储的都是指针变量(int*),所以看似是二级指针;
三、一维数组名是不是指针?
它不是真正的指针;一般情况是数组首元素地址(指针常量),此时是指针,有两种特殊情况不是:
int
arrayName[5] = { 0 };
1.
sizeof(arrayName); 计算出来的是数组内存的大小,单位是字节;
2.
int *p = &arrayName; 此时&arrayName是整个数组的指针,是int (*)[5]这种类型;p + 1 步长是整个数组的大小;
这个操作时错误的,因为&arrayName要赋值给int (*p)[5];这样的数组指针,而不能赋值给int*的指针;
3. int *p = arrayName;是正确的,对p操作时,p[0]、p[1]都可以,请问p[
负数可以吗];
答:可以的,eg:p[-1]就是相当于 *(p - 1);具体是取哪个地址的内容,要看p的当前指向,在计算-1后的位置;