从几道腾讯笔试题谈数组名与指针的思考

时间:2014.04.18
地点:基地二楼
----------------------------------------------------------------------------------------

一、题目

#include<iostream>
using namespace std;
int A(char a[10]) 
{ 
	return sizeof(a); 
}
int main(){
	char a[10]; 
	int result = sizeof(a)* 10 + A(a) * 2;
	cout << result << endl;
	return EXIT_SUCCESS;
}

给出打印结果 ?

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

二、数组名与指针

关于数组名关于数组名要明确这么几点 :
1.数组名不是指针数组名的实质是在于它是指代的实体是一种数据结构,这种数据结构就是数组。所以:
int a[10];
cout<<sizeof(a);
结果将会是40,因为在这里a指代的是int型的数组,该数组大小为10

2.数组名的外延
正如上面所说,数组名本质上是指代一种数据结构,但它的外延是数组名可以转化为指向其指代实体的指针,而且是一个指针常量,既然这个指针是一个常量的话就不可以对它进行修改和更新操作,比如:
int a[10];
a++;

这样子编译是通不过的。


3.指向数组的指针是另外一种变量类型,大小为4byte,仅仅意味着数组的存放地址,因为在函数中,我们常用到指向数组的指针。


4.数组名在很多用途下行为类似指针

比如strcpy函数原型是接受两个参数均为char型指针,但在调用时我们可以传给它两个数组名,所以在这里数组名行为类似指针。


5.数组名的去数据结构内涵
数组名去内涵表现为两点:一是数组名作为函数形参时,在函数体内,会失去它本身的数组数据结构这种内涵,在函数体内它仅仅表现为一个指针,二是而且,在失去它内涵的同时,也失去了常量特性,在函数体内它作为一个普通指针,可增可减可修改。
----------------------------------------------------------------------------------------

三、答案解析

有了这样的背景后,我们再来看那个笔试题
#include<iostream>
using namespace std;
int A(char a[10]) 
{ 
return sizeof(a); 
}
int main(){
char a[10]; 
int result = sizeof(a)* 10 + A(a) * 2;
cout << result << endl;
return EXIT_SUCCESS;
}


sizeof(a)  即对数组a求大小,为10
A(a)是将数组名作为函数实参,它的身份沦为普通指针,此时sizeof(a) 为 4
所以输出结果为 108
----------------------------------------------------------------------------------------

四、在来一个腾讯笔试题

#include<iostream>
using namespace std;
void f(char** p)
{
	*p += 2;
}
int main(){
	char* a[] = { "123", "abc", "456" }, **p;
	p = a;
	f(p);
	cout << (**p) << endl;
	return EXIT_SUCCESS;
}


解析:首先定义了一个数组a,该数组a里面存的是char* ,即a[0]是一个指向“123”的指针,a[1]是一个指向“abc"的指针....
然后p是一个指向 指针类型的指针,我们将数组a的首地址即数组地址赋给了p,因为p指向了该数组,当然我们知道p 是指向 指针类型的指针,*p便是指向对应数据类型的指针了,*p指向的char类型,于是*p+=2即向后滑动了2个byte,指向数组a[0][2]处了,***p即字符3,在此处将被打印出来。

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

五、还来一道腾讯笔试题

int main(){
	char p1[] = "Tencent";
	void* p2 = malloc(10);
	cout << sizeof(p1) << " " << sizeof(p2) << endl;
	return EXIT_SUCCESS;
}


解析:此处p1是数组名,sizeof(p1)计算的是数组大小,为8byte(加上了一个空字符表示结尾),sizeof(p2),p2是一个指针,大小为4byte
----------------------------------------------------------------------------------------

六、还再来一个腾讯笔试题

#include<stdio.h>
char* getMem(void)
{
	char* p = "Hello World";
	p[5] = 0x0;
	return p;
}
void test(void)
{
	char* s = 0x0;
	s = getMem();
	printf("The output is: %s",s);
}
int main()
{
	test();
	return 0;
}

解析:s是个char* 型指针,初始化为0x0,即一开始是指向这片地址,后面调用了一个getMen函数,指向一片新地址,这片地址中存了“Hello World",并且在使用s打印字串之前,我们对字串进行过修改,将它中间的空格去换成了结束符’\0‘,这样在用printf按字符串打印时打印到Hello完成碰到结束字符时它就不再打印了。

注意:上面的解析其实是我的想当然,题目是原题,也不晓得是怎么回事,是故意的呢还是不故意的呢?但当我亲自调试时出现了断错误,究其原因,一方面是自己基础还不到位,人家稍微一糊弄下就掉入陷阱了,在getMen函数中,char*p ="hello wordl"; 这一句只是声明了一个指针变量p,它指向字串”hello world“,而”hello world"是个常量字串,在程序中没有使用new或者malloc之类的给它在堆上分配空间,所以编译器会给它分配在常量区上,而常量区上的字符串的值是不允许被修改的,所以程序运行时会出现断错误。










评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值