面试题-指针-指针与数组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chen1083376511/article/details/82714593

返回目录:https://blog.csdn.net/chen1083376511/article/details/82723709

+问题:

问:数组与指针的区别?

答:数组是多个元素的集合,在内存中分布在地址相连的单元中,所以通过其下标访问不同单元的元素。指针是一种变量,只不过它的内存单元中保存的是一个标识其他位置的地址。由于地址也是整数,在32位平台下,指针默认为32位。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:数组和指针的异同点?

答:待更新。。。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
+问题:
问:说说char a1[]=“hello”和char *a2="hello"的区别?
答:

a1是一个数组,定义时开辟了数据内存,把常量“hello”赋值给a1(即拷贝),所以常量占有一块内存,而a1又开辟了一块相等的内存。
a2是一个字符类型的指针,指向一个常量"hello"的地址,仅仅只有常量占有内存,而指针本身占有内存为4个字节。(在32位机器中)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

扫描二维码关注公众号,回复: 5512851 查看本文章

问题:

问:下面的输出结果是?

void *fun(char *arr)
{
    char *arr2 ="world";
    arr = arr2;
    return arr;
}
int main()
{
    char *ch = "hello";
    fun(ch);
    cout << ch << endl;
    return 0;
}

:hello

分析:

这道题主要考指针作为形参的知识点,考时容易出错。由于arr是形参,属于局部变量,作用只在fun函数里面,调用函数完了之后,arr就被释放掉了。实参ch指向仍然不会改变指向。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:下面哪个语句不合法?

char a[10] = {'a'};
 char b[10] = { 'b' };
 a= b;

答:a=b;语句不合法。因为这里数组名a和b是字符指针类型的(char*),a作为左值时,是不可修改的值。

分析:
当数组名为左值时,它的类型是字符数组;当数组名为右值时,它的数据类型是字符指针。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:下面代码的输出结果是什么?
int pstr(char str[])
{
 return (int)(sizeof(str)-1);
}
void main()

 char a[20] = "Hello world";
 printf("%d",pstr(a));
}

答:3

分析:

当用函数传递的数组指针的时候就自动退化为指针了,而指针的长度是4,你减去1自然就是3了.

修改如下:

void main()

 char a[] = "Hello world";
 int len = sizeof(a)-1;
 printf("%d",len);
}

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

+问题:

问:下面代码输出结果是什么?

void main(void)
{
 char *b = "hello";
 cout << sizeof(b) << endl;
 cout << sizeof(*b) << endl;

}
答:

4 1

分析:sizeof(b) 中b是char*类型的,输出的结果是指针类型的长度。而sizeof(*b) 中的*b是char类型的,长度为1.

cout<<sizeof(char)<<endl;结果是1

cout<<sizeof(int)<<endl;结果是4

cout<<sizeof(unsigned int)<<endl;结果是4

cout<<sizeof(long int)<<endl;结果是4

cout<<sizeof(short int)<<endl;结果是2

cout<<sizeof(float)<<endl;结果是4

cout<<sizeof(double)<<endl;结果是8

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:下面语句的输出结果是什么?

char ch[]="Hello";

char *p=&ch[0];

cout<<p;

答:输出结果:Hello

分析:
因为数组第一个元素(即ch数组中序号为0的元素)的地址就是数组的首地址,因此,使用指针指向数组第一个元素的地址就是指向数组的首地址。当输出的时候,指针指向的数组元素都输出来了。不过有读者会有疑问,为什么p直接输出数组的全部内容了,而不是数组的首地址呢。详细分析,请看下一道的...下一道题目的分析。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
问题:
问:说说为什么下面代码中“char *p2=&ch;”和“char *p2”是错误的?

char ch[]="hello";
char *p1=ch;
char *p2=&ch;

char *ch2="hello";
char *p3=ch2;
char *p4=&ch2;

答:
char ch[]="hello";
char *p1=ch;//正确
char *p2=&ch;//错误
因为&取地址符的ch是char(*)[6]类型的,也就是数组指针类型,意思是一个指向整块数组的指针。所以指针p2指向的变量的数据类型不一致。因此需要强制转换才能通过,即char *p

char *ch2="hello";
char *p3=ch2;//正确
char *p4=&ch2;//编译通过,但输出结果错误
因为&取地址符的ch2是char **类型的,也就是二级指针。p4指针指向的变量的数据类型不一致。但是,如果强制转换的话,输出的结果和第一个是不一样的,会出现乱码。


把&ch和&ch2强制转换成char*类型的区别:
由于ch本身是一个字符数组,取地址符并强制转换之后,指针仍然指向该数组ch的首地址。而&ch2是一个二级指针,强制转换之后,指向的是ch2本身的地址,而不是“hello”这个常量的地址。实践时,把char类型换成int型就容易理解了。
---------------------------------------------------------------------------------------------------------------------------------------------
问题:
问:下面代码有错误吗?

char ch[]="hello";
char *p=ch;
ch[4]=p[0];
printf("%c\n",ch[4]);
printf("%s\n",ch);

答:没有出现错误。

char ch[]="hello";
char *p=ch;
ch[4]=p[0];//p[0]相当于p+sizeof(char)*0
printf("%c\n",ch[4]);//结果:h
printf("%s\n",ch);//hellh
p++;
printf("%s\n",p);//结果:ellh

---------------------------------------------------------------------------------------------------------------------------------------------
问题:

问:下面代码的输出结果是什么?

void main(){
 char*ch="Hello";//与上一题char[]="Hello"是一样的,即假如ch="Hello"=0x1001(0x1001是ch数组的首地址)
 char *p =ch;//也可以直接char *p="Hello";
 char *p0 = &ch[0];
 char *p1 = &ch[1];
 //输出指定的地址对应的内容+指向地址后的几个字符
 cout << "p:"<<p<<endl;
 cout << "p0:"<<p0 << endl;
 cout << "p1:"<<p1<<endl;
//单个字符的输出
 cout << "*p:"<<*p << endl;
 cout << "*p0:"<<*p0 << endl;
 cout <<"*p1:" <<*p1 << endl;

}
答:输出结果:

p:Hello
p0:Hello
p1:ello
*p:H
*p0:H
*p1:e
分析:
由于在C语言中没有真正的字符串类型的,但是正是因为数组元素的地址是连续的,所以可以通过字符数组来表示字符串。由于字符串常量的本质是一个地址,编译器就会为该字符串常量分配地址,比如说分配ch数组的内容“Hello”地址,依次是H:0x1001,e:0x1002,l:0x1003,l:0x1004,o:0x1005,/0:0x1006。
而指针变量保存的是地址,它保存该数组ch的首地址,当指针输出结果时候,输出来的字符串当作是地址一样显示出来了,也就是说指针指向的字符数组哪一段地址,就会把这地址后面的内容全部显示出来,假如p1=&ch[1],就会把ch数组中的第2个元素的地址以及以后的地址都显示出来。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
问题:
问:下面代码输出结果是?
void main()
{
char a[]="hello";
char *s=a;
s[0]='B';//正确
printf("%s\n",a);

char a2[]="world";
char *s2=a2;
a2[2]=s2[0];//把"r"改变为"w"
printf("a2的第三个字符:%c\n",a2[2]);
printf("%s\n",s2);
}

答:输出结果:
Bello
a2的第三个字符:w
wowld
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
问题:
问:下面代码哪条语句是错误的?

char ah[]="hello";
char *aw="world";
char *sh=NULL;
ah=sh;
ah[2]=aw[2];

char *sw=NULL;
aw=sw;
printf("%s",aw);

答:
char ah[]="hello";
char *aw="world";
char *sh=NULL;
ah=sh;//错误,不能把指针赋值给数组ah。因为ah本身是一个数组,数组一旦创建之后,ch一定是该数组的首地址,不能是其他的地址,所以不能把sh这个指针指向的地址赋值给ch。
ah[2]=aw[2];
赋值给a[2],a[2]的值会改变。

char *sw=NULL;
aw=sw;
printf("%s",aw);//结果:(null)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
问题:
问:下面代码的输出结果?
void main()
{
char a[]="hello";
char *p="B";
a[2]=*p;
printf("%s\n",a);

char *b="world";
b+=2;
a[0]=*b;
printf("%s\n",a);
}

答:
heBlo
reBlo
分析:
void main()
{
char a[]="hello";
char *p="B";
a[2]=*p;//正确
printf("%s\n",a);

char *b="world";
b+=2;//b指向的常量中的第3个字符地址。
a[0]=*b;//正确
printf("%s\n",a);
}
---------------------------------------------------------------------------------------------------------------------------------------------------------
问题:
问:下面代码的输出结果是?

char a[]="hello";
char *s=a;
for (int i = 0;i<strlen(a);i++)
{
  printf("%c", s[i]);
 printf("%c", *s++);
}
 printf("%s\n",s);

答:
char a[]="hello";
char *s=a;
for (int i = 0;i<strlen(a);i++)
{
  printf("%c\n", s[i]);//输出的结果是H  e  l  l  o
  printf("%c\n", *s++);//输出的结果是H  e  l  l  o
}
 printf("%s\n",s);//输出同样的结果:He110
 //注意:printf("%s", *s);执行程序会崩溃,因为%s输出的是字符串,而不是单字符
 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:为什下面代码中,a可以赋值给s?

char* a[]={"heng","yang","shi","fan"};

char **s=a;

答:可以。
由于数组a的首地址可以赋值给s,而且数组a的首地址的内容也可以是另外字符串的地址,即a数组的首地址是“Hello”而“Hello”首地址是“H”。

分析:

char* a[] = { "heng", "yang", "shi", "fan" };//其实a指针数组可以看成**a就容易理解了
char **s = a;
printf("%s\n", *s);///输出“Heng”是字符串
printf("%c\n", **s);//注意%c,输出“H”是一个字符
printf("%s\n", *a);//输出“Heng”是字符串
printf("%c\n", **(a + 1));// 输出“y”是一个字符
printf("%c\n", *(*a+1));//注意%c,输出“e”是一个字符

对于char**s="Hello world";是错误的,因为s是char**类型,而“Hello world”是char*类型。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

+问题(慧通面试):

问:下面代码的输出结果是 什么?

void main(){
 char str1[] = "abc";
 char str2[] = "abc";
 const char str3[] = "abc";
 const char str4[] = "abc";
 const char *str5 = "abc";
 const char *str6 = "abc";
 char *str7 = "abc";
 char *str8 = "abc";
 cout << (str1 == str2) << endl;
 cout << (str3 == str4) << endl;
 cout << (str5 == str6) << endl;
 cout << (str7 == str8) << endl;
}

答:

0   0   1   1

分析: 

这道题主要考察了笔者对指针的理解。

由于str1和str2这两个字符数组的首地址是不同的,所以等号为假,即结果是0;

由于str3和str4这两个常量字符数组的首地址是不同的,所以等号为假,即结果是0;
由于str5和str6这两个指针都指向字符串“常量”的地址,所以这两个指针保存的地址是相同的。

由于str7和str8这两个常量指针都指向字符串“常量”的地址,所以这两个常量指针保存的地址是相同的。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:下面代码的输出结果是什么?

void func(char**p);
void main()
{
 char *arr[] = {"ab","ce","ef","gh","ij","kl"};
 func(arr);
}
void func(char **p)
{
 char *t;
 t = (p += 3)[-1];
 printf("%s",t);
}

A.ab           B.cd        C.ef               D.gh

答:C

分析:
p+=3即p=p+3,指向a[3],然后又移到上一个元素a[2].具体分析,在以上那几道题目。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:(慧通面试) 

问:请问以下代码有什么问题?

#inlcude<string.h>
int main()
{
 char a;
 char *str = &a;
 strcpy(str, "hello");
 printf(str);
 return 0;}

答:

书上答案,在gcc或者VC6.0中:

int main(){ char a[20]; char *str = &a; strcpy(str, "hello"); printf(str); return 0;}
在VS环境中实践得到的答案:
int main(){ char a[20]; char *str = a; strcpy_s(str, 20,"hello"); printf(str); return 0;}
分析:

由于str并没有分配内存空间,会发生异常。问题出在一个吻字符串赋值进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内存读写而导致程序崩溃。

---------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:写出下面代码的输出结果

#include<stdio.h>
int main()
{
 int arr[] = { 1, 2, 3, 4, 5 };
 int *p = arr;


 printf("%d ",arr[2]);
 printf("%d ", *(arr+2));
 printf("%d ",p[2]);
 printf("%d ",*(p+2));


 *(p + 2) += 3;
 printf("%d ", *(p+2));
 return 0; 
}

答:

输出结果:

3 3 3 3 6

分析:

#include<stdio.h>
int main()
{
 int arr[] = { 1, 2, 3, 4, 5 };
 int *p = arr;
 printf("%d ", arr[2]);
 printf("%d ", *(arr + 2));
 printf("%d ", p[2]);//作用和arr[2]一样,p[]数组与aa[]用法相似
 printf("%d ", *(p + 2));//
    *(p + 2) += 3;//相当于*(p+2)=*(p+2)+3,即*(p+2)=3+3
 printf("%d ", *(p + 2));//只是把*(p+2)当成变量来输出结果
 p++;
 printf("%d ", *p);//这里的结果是2,是arr[1].p指向下一个元素
第一,其实当指针作为运算时,把arr当作p指针处理不难理解。例如*(arr+2)和*(p+2)的作用是一样的,虽然数组与指针的本质不相同。
第二,p++是指向下一个元素的地址,p改变成下一个元素的指针。而当p+2是指向下第二个元素的地址,与arr+2分析相同,但是p指向还是第一个元素。即p++为p=p+1,而p+2始终不能改变p指向,除非p=p+2
*(p+i) = p[i]= arr[i]=*(arr+i)

注意:p[]与a[]
 return 0;
}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:下面代码的输出结果是()

main()

{

char *p;

char a[10]={1,2,3,4,5,6,7,8,9};

p=&(a+1)[3];

printf("%d",*p);

}

A.2                  B.3                    C.4                      D.5

答:D

分析:
在上一题目可知,在这道题中,a+1是数组首元素的下一个元素的地址,a+1可看成是指针(本质上与指针有区别),(a+1)[3]=(a+1)+3所以(a+1)[3]输出的是数组a中第五个元素,即a[4]

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:
问:下面代码的输出结果是什么?

int arr[]={1,2,3,4,5};

int *ptr=arr;

*(ptr++)+=10;

printf("%d  %d ",*ptr,*(++ptr));

答:

3  3

分析:
本题考察了ptr++与++ptr的区别。ptr++:先输出ptr,再自增。而++ptr:先自增,再输出ptr。

*(ptr++)+=10;语句很容易分析错误,更不能拆分为*(ptr++)=*(ptr++)+10来分析,因为它们两之间还是有区别的。

*(ptr++)+=10分析:

第一步,由于优先级()高于*,所以ptr++提取出来,其他先不管。

第二步,ptr++首先输出的是还没有自增的ptr,所以就会有*ptr+=10,这时还没有自增的ptr指向arr首地址,所以*ptr就是arr[0]的值为11,然后ptr才自增,这时ptr指向arr数组的下一个元素,即arr[1]。

*(ptr++)=*(ptr++)+10分析:

第一步,由于优先级()高于*,所以ptr++提取出来,其他先不管。

第二步,ptr++首先输出的是还没有自增的ptr,所以就会有*ptr=*ptr+10,这时还没有自增的ptr指向arr首地址,所以*ptr就是arr[0]的值为11,然后ptr自增两遍,即左右值都要自增,得到的最终结果ptr指向arr[2].

printf("%d  %d ",*ptr,*(++ptr));也容易出错。

输出的规则是从右到左,所以*ptr是执行*(++ptr)之后输出的。

------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:
问:设有“int w[3][4];”, p表示指向数组w的数组指针,则p的初始化语句是什么?
答:
int *p=w;
分析:指针初始化有两种方式:
1.int *p;
p=w;
2.int *p=w;
第一种方式是通过两条语句通过的,而第二种只通过一条语句完成,即初始化语句。所以选择第二种。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

问题:

问:下面代码是否正确?

int a[2][3]={1,2,3,4,5,6};
int *p=a;
int *p=a[1];
cout<<*p<<endl;

答:

int a[2][3]={1,2,3,4,5,6};

 int *p=a;//错误,数据类型不一致
int *p=a[1];///指向a[1],也就是a[1][0],a[1][2],a[1][3]的合段,而&a[1]是不合法的

cout<<*p<<endl;//结果是4,输出a[1][0],默认数组首地址的内容 

猜你喜欢

转载自blog.csdn.net/chen1083376511/article/details/82714593