比如说在下面的这段程序中
#include <stdio.h>
int main()
{
char str[] = "I love LunZiGongChang!";
int count = 0;
while (*str++ != '\0'){
count++;
}
printf("总共有%d个字符!\n", count);
return 0;
}
执行代码会得到如下的错误
#include <stdio.h>
int main()
{
char str[] = "I love LunZiGongChang!";
char *p= str;
int count = 0;
while (*p++ != '\0'){
count++;
}
printf("总共有%d个字符!\n", count);
return 0;
}
总共有22个字符!
这个地方还可以引申出一个问题:c 中while(*p++);与while(*p){p++;}有什么区别?
区别在于退出循环后, p的值不一样。
while( *p++ ); //当*p=0时,退出循环,此时p++仍然执行了
while( *p ) p++; //当*p=0时,退出循环,此时p++不再被执行
例如 char *p="ABCD";
执行完第一个while循环后,p指向的是’\0’后面的一个字节,p的结果是未知的
而如果是执行第二个循环,则p指向的是’\0’,也就是’D’后面的一字节,即p=’\0’。如果忘记了可以回顾一下之前的文章中第三部分 “自增自减运算符” 中的内容。
指针数组,从名字来理解,很容易看出它是一个数组,里面装的是指针。比如下面的这段代码
int *p1[5];
它就是一个指针数组,我们可以从运算符的优先级和结合性进行分析。数组下标的优先级要比取值运算符的优先级高,所以先入为主,p1 被定义为具有 5 个元素的数组。那么数组元素的类型呢?是整型吗?显然不是,因为还有一个星号,所以它们应该是指向整型变量的指针。所示上述代码所定义的数组如下所示
即指针数组是一个数组,数组中的元素是指针变量。
比如说下面这段代码
#include <stdio.h>
int main()
{
char *p1[5] = {
"轮子工厂厂长招亲!",
"身高不限",
"肤色不限",
"身材不限",
"只要你不嫌弃厂长丑帅丑帅的~"
};
int i;
for (i = 0; i < 5; i++){
printf("%s\n", p1[i]);
}
return 0;
}
我们将指针数组中的每个元素初始化为一个字符串,这里之所以可以这样写是因为一个指针可以使用 char *p = "sss"
的方式进行初始化,所以如果想初始化一个指针数组,就可以通过上面的方式进行。在打印输出中使用 p1[i]
而不是 *p1[i]
,*p1[i]
将取出的是字符串中的第一个字符,而不能打印整个字符串。执行上面的代码会得到如下的结果
轮子工厂厂长招亲!
身高不限
肤色不限
身材不限
只要你不嫌弃厂长丑帅丑帅的~
这个时候数组从 array[0] 到 array[1] 虽然只变换了一个位置,但实际上跳过了整个第一行,因此
同理对于一个三维数组
int Sarray[2][2][3] = {
{ { 1, 2, 3 }, { 4, 5, 6 } },
{ { 7, 8, 9 }, { 3, 6, 8 } }
};
数组指针,顾名思义,是一个指向数组的指针,比如说下面这个
int (*p2)[5];
从运算符的优先级和结合性进行分析,因为圆括号和数组下标位于同一个优先级队列,所以我们就要看先来后到的问题了。由于它们的结合性都是从左到右,所以 p2 先被定义为一个指针变量。那么它指向谁?还能有谁?后边还紧跟着一个具有 5 个元素的数组,p2 指向的就是它。由于指针变量的类型事实上就是它所指向的元素的类型,所以这个 int 就是定义数组元素的类型为整型。即如下图所示
#include <stdio.h>
int main()
{
int temp[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &temp;
int *pp = temp;
printf("%p\n", temp);
printf("%p\n", &temp[0]);
printf("%p\n", &temp);
printf("----------------\n");
printf("%p\n", pp);
printf("%p\n", pp+1);
printf("%p\n", p);
printf("%p\n", p+1);
printf("%p\n", *p+1);
return 0;
}
输出的结果如下
0x7ffe2758e710
0x7ffe2758e710
0x7ffe2758e710
----------------
0x7ffe2758e710
0x7ffe2758e714
0x7ffe2758e710
0x7ffe2758e724
0x7ffe2758e714
根据上面的知识可以知道,下面的代码明显是错误的。
#include <stdio.h>
int main()
{
int (*p2)[5] = {1, 2, 3, 4, 5};
int i;
for (i = 0; i < 5; i++)
{
printf("%d\n", *(p2 + i));
}
return 0;
}
它的本来用意是想用指针法的形式将数组中的每一个元素打印出来,但是却得到如下的结果
从 warning 的提示信息可以看出是第六行指针的定义及初始化的错误。
#include <stdio.h>
int main()
{
int temp[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &temp;
int i;
for (i = 0; i < 5; i++){
printf("%d\n", *(p + i));
}
return 0;
}
执行之后发现程序依然会报错,如下所示
将程序修改为如下的形式便可以正常执行了
#include <stdio.h>
int main()
{
int temp[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &temp;
int i;
for (i = 0; i < 5; i++){
printf("%d\n", *(*p + i));
}
return 0;
}
我们可以从下面这个例子加深自己对数组指针的理解
#include <stdio.h>
int main()
{
int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int *p = (int *)(&array + 1);
printf("%d\n", *(p - 6));
return 0;
}
上面的例子是从数组指针的角度进行考虑的,下面的这个例子将从指针数组的角度进行考虑,比如下面的这段代码会输出和上面一样的结果。
#include <stdio.h>
int main()
{
int array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int (*p)[10] = &array;
printf("%d\n", *(*(p+1)-6));
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- ovod.cn 版权所有 湘ICP备2023023988号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务