关于指针,以及数组,其实对于一维数组与与指针来说,是比较简单的,这里不再说明。
我们强调的是二维数组与指针,下面是我的一些写法,囊亏了很多写法,是我个人的理解;
第一种形式(*p)[30],有一个数组大小为30元素均是(char )字符类型,这个数组地址是*p
#include "stdio.h"
#include "stdlib.h"
int main(void)
{
int i,j;
char (*p)[30];
p = (char (*)[30])malloc(2*sizeof(char[30]));
if(p == NULL)
return -1;
printf("mallc初始化...\n");
for(i=0;i<2;i++)
{
printf("请输入第%d行:",i+1);
scanf("%29s", *(p+i));
getchar(); // 清除换行符
}
printf("\n*******String01**************\n");
for(i=0;i<2;i++)
{
printf("第%d行:%s\n",i+1, *(p+i));//*(p+i) = p[i]
}
printf("\n*******String02**************\n");
for(i=0;i<2;i++)
{
printf("第%d行:%s\n",i+1, p[i]);
}
printf("\n*******Char01**************\n");
for(i=0;i<2;i++)
{
j=0;
printf("\n请输入第%d行:", i+1);
while( *(*(p+i) + j) != '\0')
{
printf("%c", *(*(p+i) + j));//*(p+i) = p[i] ,指向p地址,往后加,再取值
j++;
}
}
printf("\n*******Char02【需注意此种写法!!!】**************\n");
for(i=0;i<2;i++)
{
j=0;
printf("\n请输入第%d行:", i+1);
while( (*(p+i))[j] != '\0')
{
printf("%c", (*(p+i))[j]);//(*p)[30]是一个char型的 ,*(p+i) = p[i] ,
j++;
}
}
}
下面集中一下:
*(*(p+i) + j)
这是您使用的一种方法,使用纯指针算术。
(*(p+i))[j]
这也是您使用的另一种方法,结合了指针算术和数组索引。
p[i][j]
最常见和直观的数组索引写法。
*(p[i] + j)
结合了数组索引和指针算术。
*(&p[0][0] + i*30 + j)
将二维数组视为一维数组,使用地址算术。
*((char *)p + i*30 + j)
将 p 视为指向字符的指针,然后进行指针算术。
(*(char (*)[30])p)[i][j]
将 p 显式转换为指向30个字符数组的指针,然后进行索引。
((char *)p)[i*30 + j]
将 p 转换为字符指针,然后使用一维数组的索引方式。
*(*p + i*30 + j)
将 p 解引用为指向整个数组的指针,然后进行算术运算。
(p[i])[j]
与 p[i][j] 等价,但增加了括号以强调 p[i] 是一个指针。
第二种形式*p[30],有30个元素,都是指针类型
#include "stdio.h"
#include "stdlib.h"
int main(void)
{
char *p[30];
int i,j;
for(i=0;i<2;i++)
{
p[i] = (char *)malloc(2*30*sizeof(char));
if(p[i] == NULL)
return -1;
printf("p[%d]空间分配完成!\n", i+1 );
}
printf("\n--------------------------------\n");
for(i=0;i<2;i++)
{
printf("请输入第%d行:",i+1);
scanf("%29s", *(p+i));
getchar();
}
printf("\n---------------String01-----------------\n");
for(i=0;i<2;i++)
{
printf("\n第%d行:%s", i+1, *(p+i));//*(p+i) = p[i]
}
printf("\n---------------String02-----------------\n");
for(i=0;i<2;i++)
{
printf("\n第%d行:%s", i+1, p[i]);
}
printf("\n---------------Char01-----------------\n");
for(i=0;i<2;i++)
{
printf("\n第%d行:", i+1);
j=0;
while( p[i][j] != '\0')
{
//当我们对一个指针使用 [] 操作符时,它实际上是一种间接寻址的简写形式
printf("%c", p[i][j]);//p[i][j] 实际上等同于 *(p[i] + j);
j++;
}
}
printf("\n---------------Char02-----------------\n");
for(i=0;i<2;i++)
{
printf("\n第%d行:", i+1);
j=0;
while( *(*(p+i)+j) != '\0')
{
printf("%c", *(*(p+i)+j));//*(p+i) = p[i]
j++;
}
}
printf("\n---------------Char03-----------------\n");
for(i=0;i<2;i++)
{
printf("\n第%d行:", i+1);
j=0;
while( (*(p+i))[j] != '\0')
{
printf("%c", (*(p+i))[j]);//[]的优先级要高于*,所以要加()
j++;
}
}
}
我们同样总结一下:
p[i][j]
这是最常见和直观的写法。
*(*(p+i)+j)
这是使用指针算术的写法,等同于 p[i][j]。
(*(p+i))[j]
这也等同于 p[i][j],但使用了部分指针算术。
*(*p + i*60 + j)
假设每行分配了60个字符,这种写法将二维数组视为一维数组。
*(p[i] + j)
这结合了数组索引和指针算术。
*(&p[0][0] + i*60 + j)
类似于第4种,但使用了地址运算。
(p[i])[j]
这与 p[i][j] 等价,但增加了括号以强调 p[i] 是一个指针。
*((char *)p + i*60 + j)
将 p 视为指向字符的指针,然后进行指针算术。
(*(char (*)[60])p)[i][j]
将 p 转换为指向60个字符数组的指针,然后进行索引。
(*(char (*)[2][60])p)[i][j]
将 p 视为指向2行60列的二维数组的指针。
总结部分,稍作了解,不需要全都明白,应为我也没明白,O(∩_∩)O哈哈~