1、选择题
1.1、若有下面的变量定义,以下语句中合法的是( A )。
int i,a[10],*p;
A) p=a+2; B) p=a[5];
C) p=a[2]+2; D) p=&(i+2);
解析:指针是用来存储变量地址,数组的地址可以用变量名代替,a+2表示数组首地址后移2位,表示a[2]的地址,所以合法,a[5]表示的是数组元素的值,不是地址,所以不合法,a[2]+2表示数组第二个元素的值+2,得到的是一个值,不是地址,所以也不合法,表达式i+2产生的是一个整数值,不能对整数取地址,所以也不合法
1.2、有以下程序
main()
{
int a[3][3],*p,i;
p=&a[0][0];
for(i=0;i<9;i++)
p[i]=i;
for(i=0;i<3;i++)
printf("%d ",a[1][i]);
}
程序运行后的输出结果是 D
A)0 1 2
B)1 2 3
C)2 3 4
D)3 4 5
解析:for(i=0;i<9;i++ ) p[i]=i; 这句是将0~9赋给数组a[3][3], for(i=0;i<3;i++) printf("%d ",a[1][i]);这句是打印第二行的元素a[1][0]~a[1][2],即3 4 5
1.3、有以下程序
int main()
{ int a[3][2]={0}, (*ptr)[2],i,j;
for(i=0;i<2;i++)
{ ptr=a+i;
scanf("%d",*ptr);
*ptr++;
}
for(i=0;i<3;i++)
{
for(j=0;j<2;j++)
printf("%2d",a[i][j]);
printf("\n");
}
}
若运行时输入:1 2 3<回车>,则输出结果为 D
A)产生错误信息
B)1 0
2 0
0 0
C)1 2
3 0
0 0
D)1 0
2 0
3 0
解析:定义了一个3x2的二维数组a
,并初始化为0。定义了一个指向包含2个整数的数组的指针ptr
。使用循环,每次将ptr
指向a
的某一行,并读取一个整数到这一行。输入1 2 3
将分别被读取到a[0][0]
, a[1][0]
和a[2][0]
。所以结果为 1 0 2 0 3 0
1.4、有以下程序
main()
{ int a[]={1,2,3,4,5,6,7,8,9,0},*p;
printf("%d,",*p);
}
程序运行后的输出结果是 A
A)1,2,3,4,5,6,7,8,9,0,
B)2,3,4,5,6,7,8,9,10,1,
C)0,1,2,3,4,5,6,7,8,9,
D)1,1,1,1,1,1,1,1,1,,1,
解析:程序首先定义了一个包含10个整数的数组a
,然后定义了一个指向整数的指针p
。接着,程序使用for
循环遍历数组a
的每一个元素,并使用指针p
来访问和打印这些元素的值。程序中的循环从p=a
开始,即指针p
指向数组a
的第一个元素。每次循环中,p
都会递增,指向下一个元素,直到p
达到a+10
,即数组a
的最后一个元素之后的位置。在循环的每次迭代中,*p
都会解引用指针p
,得到它当前指向的元素的值,并使用printf
函数打印这个值。由于数组a
的元素是按照{1,2,3,4,5,6,7,8,9,0}
的顺序排列的,因此程序会按照这个顺序打印出数组中的每一个元素。所以,程序运行后的输出结果是:1,2,3,4,5,6,7,8,9,0
1.5、有以下程序
main()
{
char s[]="159",*p;
p=s;
printf("%c",*p++);
printf("%c",*p++);
}
程序运行后的输出结果是 A
A)1 5 B)1 6 C)1 2 D)5 9
解析:指针 p
被声明,并且被赋值为 s
的地址,也就是 s
数组第一个字符 '1'
的地址。printf("%c",*p++);
语句中,*p++
表示先解引用指针 p
(也就是获取指针当前指向的字符),然后将指针 p
向后移动一位。所以,第一次执行此语句时,会打印出 s
数组的第一个字符 '1'
,然后 p
会指向 '5'
。第二次执行 printf("%c",*p++);
时,同样先解引用 p
(此时 p
指向 '5'
),然后打印出 '5'
,接着 p
会向后移动一位,指向 '9'
。因此,程序运行后的输出结果是:15
1.6、有以下程序
point(char *p)
{
p+=3;
}
int main()
{ char b[4]={'a','b','c','d'}, *p=b;
point(p); printf("%c\n",*p);
}
程序运行后的输出结果是 D
A)a B)b C)c D)d
解析:在这个程序中,point
函数接收一个字符指针p
作为参数,并将这个指针向后移动3个位置。在main
函数中,定义了一个字符数组b
,并用指针p
指向它的起始位置。接下来,调用point
函数并将p
作为参数传递。在point
函数中,p
被增加了3,这意味着p
现在指向了数组b
中第4个元素的位置。然后,打印出p
所指向的字符程序将输出'd'
。因此,程序运行后的输出结果是 d
。
1.7、设有如下定义语句 int m[ ]={2,4,6,8}, *k=m;
以下选项中,表达式的值为 6的是 A
A *(k+2) B k+2 C *k+2 D *k+=2
解析:*(k+2)
:这个表达式先计算k+2
,得到指向m[2]
的指针。然后,通过解引用这个指针,我们得到m[2]
的值,即6。k+2:
这个表达式计算了k
指针加上2,得到指向m[2]
的指针。但是,它并没有解引用这个指针,所以它的值是m[2]
的地址,而不是它的值。*k+2:
这个表达式先解引用k
,得到m[0]
的值,即2。然后,将2加上2,得到4。*k+=2:
这个表达式先解引用k
,得到m[0]
的值,即2。然后,将这个值加2,并将结果(4)存回m[0]
。但是,这个表达式本身的值是m[0]
加2之前的值,即2。
1.8、若有定义语句:int year=2009,*p=&year;,以下不能使变量 year 中的值增至 2010 的语 句是( D )。
A)*p+=1; B)( *p)++; C)++(*p); D)*p++;
解析:*p+=1;
这个语句会解引用指针p
(即访问 p
所指向的内存位置),然后将该位置的值增加1。因此,year
的值会从2009增加到2010。(*p)++;
这个语句也是先解引用指针p
,然后将其值增加1。同样,year
的值会从 2009 增加到 2010。++(*p);
这个语句同样是先解引用指针p
,然后将其值增加1。year
的值会从2009增加到 2010。*p++;
包含两个部分:*p
和p++
。首先,*p
会解引用指针p
,获取其指向的值(即 year
的值)。但是,由于后面紧跟着 p++
,指针p
会被递增,指向下一个内存位置。然而,这个操作并没有改变year
的值,只是改变了指针p
的指向。因此,year
的值仍然是 2009,而p
现在指向了year
之后的内存位置。综上所述,不能使变量year
中的值增至2010的语句是*p++;
1.9、设有定义:double x[10],*p=x;,以下能给数组 x 下标为 6 的元素读入数 据的正确语句是 C
A)scanf("%f",&x[6]); B)scanf("%lf",*(x+6));
C)scanf("%lf",p+6); D)scanf("%lf",p[6]);
解析:scanf("%f",&x[6]);
这个选项使用了 %f
格式说明符,这是不正确的,因为 x[6]
是一个 double
类型的变量,应该使用 %lf
。
scanf("%lf",*(x+6));
这个选项使用了 %lf
格式说明符,这是正确的。但是,*(x+6)
实际上是解引用操作,这会得到 x[6]
的值,而不是它的地址。scanf
需要变量的地址来存储输入,所以这是不正确的。
scanf("%lf",p+6);
这个选项也是正确的。p+6
是正确的,因为它给出了数组 x
第 6 个元素的地址。%lf
格式说明符也是正确的。
scanf("%lf",p[6]);
这个选项是错误的。p[6]
会得到 x[6]
的值,而不是它的地址。scanf
需要变量的地址来存储输入。
因此,正确的选项是scanf("%lf",p+6);
。
1.10、若有定义语句:char s[3][10], (*k)[3], *p; ,则以下赋值语句正确的是 BD
A)p=s; B)p=s[0]; C)p=k; D)k=s;
解析:p=s;
这个赋值是错误的。因为s
是一个二维数组,其类型是char[3][10]
,而p
是一个字符指针(char*
)。它们不兼容,因此不能直接将二维数组的地址赋给一个字符指针。
p=s[0];
这个赋值是正确的。s[0]
是二维数组s
的第一个元素,它是一个一维字符数组(类型是char[10]
)。s[0]
的地址可以赋给一个字符指针p
,因为p
可以指向一个字符数组的首字符。
p=k;
这个赋值是错误的。k
是一个指向包含3个元素的数组的指针,而p
是一个字符指针。它们不兼容,因此不能直接将k
的地址赋给p
。
k=s;
这个赋值是正确的。s
是一个二维数组,其类型是char[3][10]
。k
是一个指向包含3个元素的数组的指针,每个元素都是一个字符数组(实际上是char(*)[10]
类型)。因此,s
的地址可以赋给k
,因为k
可以指向一个二维数组的首行。
综上所述,正确的赋值语句是p=s[0];
和k=s;
1.11、有定义语句:int *p[4]; 以下选项中与此语句等价的是 D
A)int p[4]; B)int **p; C)int *(p[4]); D)int (*p)[4];
解析:int (*p)[4];
这个定义声明了一个指针,它指向一个包含4个整数的数组。这与原语句等价,因为原语句也是一个包含4个元素的数组,每个元素都是一个指针。
1.12、若有定义语句:int a[4][10], *p, *q[4]; 且 0≤i<4,则错误的赋值是 B
A)p=a B)q[i]=a[i] C)p=a[i] D)p=&a[2][1]
解析:q[i]=a[i];
这是错误的。q
是一个指向指针的数组,每个元素都是一个指针。而a[i]
是一个包含10个整数的数组,不是一个指针。因此,不能将数组a[i]
赋值给指针q[i]
。
1.13、若有以下定义
int x[10],*pt=x;
则对 x 数组元素的正确应用是 BD
A)*&x[10] B)*(x+3)
3C)*(pt+10) D)pt+3
解析:*(x+3)
这是正确的。x
是一个指向数组第一个元素的指针,所以 x+3
会得到数组中第4个元素的地址。通过解引用这个地址(使用 *
),我们可以得到数组中第4个元素的值。
pt+3
这是正确的。pt
是一个指向整数的指针,初始时指向数组 x
的第一个元素。pt+3
会得到数组中第4个元素的地址。这个表达式本身并不解引用指针,所以它是安全的。
1.14、有以下程序
#include
main()
{ int a[ ]={1,2,3,4},y,*p=&a[3];
--p; y=*p; printf(“y=%d\n”,y);
}
程序的运行结果是 D
A)y=0 B)y=1 C)y=2 D)y=3
解析:程序中有一个整数数组 a
,其元素初始化为 {1, 2, 3, 4}
。接着,定义了一个整数指针 p
,并使其指向数组 a
的最后一个元素(即 a[3]
),其值为 4。然后,程序执行了 --p;
操作,这将指针 p
向前移动一个位置,使其指向数组 a
的倒数第二个元素(即 a[2]
),其值为 3。接下来,程序执行了 y=*p;
,这将指针 p
所指向的值(即 a[2]
的值)赋给了变量 y
,因此 y
的值为 3。最后,程序输出了 y
的值,即 y=3
。因此,程序的运行结果是 y=3
1.15、设char *s = “\ta\017bc”;则指针变量s指向的字符串所占的字节数是 C
A) 6 B) 2 C) 5 D) 9
解析:给定的字符串是 s = "\ta\017bc";
。在这个字符串中,\t
是一个制表符(tab),a
是一个字符,\017
是一个八进制表示的字符(其ASCII值是15,即0x0F或017,但在这个上下文中它不会作为一个结束标志,因为它不是 \0
),b
和 c
也是字符。因此,字符串中的字符是:\t
(1字节)、a
(1字节)、\017
(1字节)、b
(1字节)、c
(1字节)。所以字符串的总字节数是5字节。
1.16、 若有定义语句:char s[3][10], (*k)[3], *p;,则以下赋值语句正确的是 CD
A)p=s; B)p=k; C)p=s[0]; D)k=s;
解析:p=s[0];
这是正确的。s[0]
是二维数组 s
的第一个元素,它是一个一维数组(类型为 char[10]
)。s[0]
的值(即地址)可以被赋给一个字符指针 p
,因为 p
可以指向一个字符数组的首地址。
k=s;
这是正确的。s
是一个二维数组,其类型是 char[3][10]
。k
是一个指向包含3个元素的数组的指针,每个元素也是一个数组。因此,s
的地址可以被赋给 k
,因为 k
的类型与 s
的类型兼容。
综上所述,正确的赋值语句是p=s[0];
和k=s;
2、填空题
2.1以下程序的输出结果是 6
#include
main()
{ int a[5]={2,4,6,8,10}, *p;
p=a+2;
printf(“%d”,*p++);
}
解析:定义了一个包含5个整数的数组 a
,其初始值为 {2, 4, 6, 8, 10}。接着定义了一个整数指针 p
。然后,p=a+2;
这行代码将指针 p
指向数组 a
的第三个元素(索引为2的元素),即值为6的那个元素。接下来,printf(“%d”,*p++);
这行代码做了两件事:1.*p
表示指针 p
当前指向的值,即6。2.p++
将指针 p
向后移动一个位置,使其指向数组的下一个元素,即值为8的那个元素。但是,由于 p++
是后自增操作,所以在 printf
函数中使用的仍然是 p
自增之前的值,即指向值为6的那个元素。因此,程序的输出结果是 6
2.2、以下程序段的定义语句中,x[1]的初值是 2 ,程序运行后输出的内容是 3 5 7 9
#include
main()
{ int x[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},*p[4],i;
for(i=0;i<4;i++)
{ p[i]=&x[2*i+1]; printf(“%d ”,p[i][0]);
}
printf(“\n”);
}
解析:当 i=0
,p[0]
指向 x[1]
,即 p[0]
的初值是 &x[1]
,即 x[1]
的地址。当 i=1
,p[1]
指向 x[3]
。当 i=2
,p[2]
指向 x[5]
。当 i=3
,p[3]
指向 x[7]
。因此,程序将输出 3 5 7 9
2.3 以下程序段的输出结果是( rgb )
#include
mian()
{ char *ch[4]={“red”,”green”,”blue”}; int i=0;
while(ch[i]);
{ putchar(ch[i][0]; i++; }
}
解析:这个程序的目的是输出数组中每个字符串的第一个字符,直到遇到'\0',数组 ch
包含三个字符串:"red", "green", "blue"。每个字符串的第一个字符分别是 'r', 'g', 'b'。因此,程序的输出结果是:rgb
2.4、以下程序的功能是:借助指针变量找出数组元素中最大值所在的位置并输出该最大值。 请在输出语句中填写代表最大值的输出项。
#include
int main()
{ int a[10], *p, *s;
for(p=a; p-a<10; p++)
scanf(“%d”, p);
for(p=a,s=a;p-a<10;p++)
if(*p>*s) s=p;
printf(“max=%d, 序号:%d\n” , *s, s - a );
}
解析:在printf
语句中,*s
代表最大值,而s - a
代表最大值在数组中的位置(从0开始的索引)。因为a
是数组的首地址,s
是指向最大值的指针,所以s - a
就是最大值在数组中的位置。
2.5 有以下程序,输出结果为 2,5
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",*(a+1),*(ptr-1));
}
解析:*(a + 1)
:a
是一个数组名,它本身就是一个指针,指向数组的第一个元素。因此,a + 1
实际上是指向数组的第二个元素a[1]
的地址。通过解引用这个地址,我们得到a[1]
的值,即2。
*(ptr - 1)
:由于ptr
指向的是数组a
之后的内存位置,ptr - 1
实际上是指向数组a
的最后一个元素a[4]
的地址。通过解引用这个地址,我们得到a[4]
的值,即5。
2.6 以下程序的功能是:借助指针变量找出数组元素中最大值所在的位置并输出该最大值。 请在输出语句中填写代表最大值的输出项。
#include
int main( )
{ int a[10], *p, *s;
for(p=a;p-a<10; p++)
scanf(“%d”,p);
for(p=a,s=a;p-a<10;p++)
if(*p>*s) s=p;
printf(“max=%d\n” , *s );
解析:在 printf
语句中,*s
代表最大值,因为 s
是一个指向数组元素的指针,而 *s
就是该元素的值。这样程序就会输出数组中的最大值
3、编程题
3.1、 有一个整型数组int [10] = {10,20,30,40,50,60,70,80,90,100};标准输入一个整型数值m(0
代码:
#include
using namespace std;
int main()
{
int arr[10]={10,20,30,40,50,60,70,80,90,100};
int m;
//从标准输入读取一个整型数值m
cin >> m;
//检查m是否在有效范围内
if(m>0&&m<10)
{
//临时数组,用于存储后m个元素
int temp[m];
//将后m个元素存储到临时数组中
for(int i=0;i=m;--i)
{
arr[i]=arr[i-m];
}
//将临时数组中的元素放回数组的前m个位置
for(int i=0;i
结果: