字符指针没什么好讲的,主要就强调一下一个点
const char* pstr="hello world";
这里的pstr指针表示的不是指向hello world整个字符串,而是指向首字符h的地址,究其原因还是因为它是char指针,步长为一个字节,也就只能一个字符一个字符的指,若存在String指针,你要说它指向hello world那就应该没问题,但这里两个指针表示的地址是相同的,只是他们步长不同,所包围笼罩的范围不同;上述两个指针都加整数1,char跳过一个字符(字节),String跳过"hello world"对应的12个字节(末尾省略了\0)
用一道有趣的面试题来巩固一下:
#include
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char *str3 = "hello bit.";
const char *str4 = "hello bit.";
if(str1 ==str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if(str3 ==str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
这里答案是什么呢?我们运行一下来看看,实践出真知:
1)str1与str2数组不同,并且数组是可变参数,所开辟的空间不同,数组名所表示的首元素地址也就不同;
2)str3与str4指向的是一个常量字符串,而且指向的是同一个常量字符串,原因是常量字符串不可更改,所以在空间中也没有创建两个的必要性,所以常量字符串在空间中是惟一的,str3、str4都指向同字符串的首字符地址,所以相同;
这里关于字符指针就不多赘述了;
哈哈,终于来这个头疼的一对兄弟了,这里是我初学时候的噩梦呀,见一次,查一次哈哈,这里我会用自己总结的方法来讲解,希望对大家有帮助!
若元素为一级指针,那便是一级指针数组 int* arr[5]------>前面int*就是arr数组元素类型;
那二级指针数组怎么表示呀,哈哈,就是int** arr[5]呗,是不是明了一些了呢。
注: 这里我是用int指针为例的,若数组元素为char那便前面也用char* arr[]即可;
这里也注意下:int* arr[10],[10]优先级高于星号,所以先和arr结合,也就是说明它是数组;
这个就讲一下表达形式: int(*arr)[5] ,这里arr先和星号结合,所以它是指针;
对于上述的例子呢,它表达的含义就是一个指向含有五个整形元素 的 数组首元素地址的指针
大家在这里一定注意区分,arr先和谁结合,就相应对应什么类型,先和星号结合那么就是指针,先和中括号结合,那么就是数组;这里就先简单介绍到这,其他的会在后面一步步巩固。
我们直到数组名代表着数组首元素的地址,但&数组名又代表什么呢,先不慌,我们来看一个代码:
#include
int main()
{
int arr[10] = {0};
printf("%p\n", arr);
printf("%p\n", &arr);
return 0;
}
这里我们发现两者表示的地址相同,难道它们没有区别吗?我们接着测试:
#include
int main()
{
int arr[10] = { 0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
return 0;
}
int main()
{
int arr[10] = { 0 };
int* arr2[20] = { 0 };
test(arr);
test2(arr2);
return 0;
}
如上面的代码,我们在使用函数的时候该如何接收呢?
这里我们列出一系列的传参方式,我来为大家分析是否可行:
//arr[10]传参:
void test(int arr[]){}
//这种方案是可行的,只是传入的数组大小不够明确,所以不建议这样
void test(int arr[10]){}
//此方案补足了上一种方案的不足,原封不动的传参当然可以
void test(int *arr){}
//这里是指针传参,arr本质为数组首元素地址,类型为int* 所以这里也没有问题
//arr2[20]传参:
void test2(int *arr[20]){}
//直接把原来的一维数组照搬,肯定没问题;
void test2(int **arr){}
//arr2的类型是int** 所以也没有问题
这里可以留意下,函数传参位置也就是上述的void test()括号内,必须保证类型一样即可,不必要求参数名称一致;
//arr[3][5]={0};
void test(int arr[3][5]){}
//直接照搬,毫无问题;
void test(int arr[][]){}
//这里就会出现问题了,对于二维数组我们在定义的时候就明确表示,二维数组行可以省略,列不可以省略;这里形参部分其实也相当于一个创建局部变量的问题,所以这里也无法成立;
void test(int arr[][5]){}
//这个形参满足类型要求,也满足二维数组创建要求,所以可以;
//test(arr);
void test(int *arr){}
//arr是一级指针,但是二维数组数组名表示的是第一行开头的地址,也就是说它的元素是第一行,而int* arr表示的步长为int,元素也就是int类型,所以类型不符
void test(int* arr[5]){}
//这是个指针数组,类型完全不符合;
void test(int (*arr)[5]){}
//数组指针,指向每行有五个元素的数组的指针,诶,这不就刚好和我们上面说的一致了吗?所以可行
void test(int **arr){}
//二维数组的数组名是一级指针不能用二级指针接收
int main()
{
int arr[3][5] = {0};
test(arr);
}
这个就不多赘述了,简单总结下:传入什么类型的指针,就用相同类型指针接收,但要注意上述数组传参中用指针接收,要注意类型;
举个例子:
#include
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
int x, y;
int input = 1;
int ret = 0;
do
{
printf( "*************************\n" );
printf( " 1:add 2:sub \n" );
printf( " 3:mul 4:div \n" );
printf( "*************************\n" );
printf( "请选择:" );
scanf( "%d", &input);
switch (input)
{
case 1:
printf( "输入操作数:" );
scanf( "%d %d", &x, &y);
ret = add(x, y);
printf( "ret = %d\n", ret);
break;
case 2:
printf( "输入操作数:" );
scanf( "%d %d", &x, &y);
ret = sub(x, y);
printf( "ret = %d\n", ret);
break;
case 3:
printf( "输入操作数:" );
scanf( "%d %d", &x, &y);
ret = mul(x, y);
printf( "ret = %d\n", ret);
break;
case 4:
printf( "输入操作数:" );
scanf( "%d %d", &x, &y);
ret = div(x, y);
printf( "ret = %d\n", ret);
break;
case 0:
printf("退出程序\n");
breark;
default:
printf( "选择错误\n" );
break;
}
} while (input);
return 0;
}
如果用函数指针数组呢:
#include
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a*b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
int x, y;
int input = 1;
int ret = 0;
int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
while (input)
{
printf( "*************************\n" );
printf( " 1:add 2:sub \n" );
printf( " 3:mul 4:div \n" );
printf( "*************************\n" );
printf( "请选择:" );
scanf( "%d", &input);
if ((input <= 4 && input >= 1))
{
printf( "输入操作数:" );
scanf( "%d %d", &x, &y);
ret = (*p[input])(x, y);
}
else
printf( "输入有误\n" );
printf( "ret = %d\n", ret);
}
return 0;
从上面这个简单的例子,我们不难看出函数指针数组在多个函数类同,作用方式相似的案例中,可以非常有效的缩短代码长度,起到简化的效果;