C语⾔经典⾯试题——(持续更新)
注:整理所有问题均来⾃换联⽹,个⼈觉得不错,可以反复思考,回过头来多看⼏遍,⽆论对于⾯试还是思维提升都有极⼤的帮助。
问:请出下⾯代码⾥的问题:
#include<stdio.h>
int main(void)
{
char buff[10];
memset(buff,0,sizeof(buff));
gets(buff);
printf("\n The buffer entered is [%s]\n",buff);
return 0;
}
答:上⾯代码⾥的问题在于函数gets()的使⽤,这个函数从stdin接收⼀个字符串⽽不检查它所复制的缓存的容积,这可能会导致缓存溢出。这⾥推荐使⽤标准函数fgets()代替。
2.请出下⾯代码中的所有错误 (题⽬不错,值得⼀看)
说明:以下代码是把⼀个字符串倒序,如“abcd”倒序后变为“dcba”
#include"string.h"
main()
{
char*src="hello,world";
char* dest=NULL;
int len=strlen(src);
dest=(char*)malloc(len);
char* d=dest;
char* s=src[len];
while(len--!=0)
d++=s--;
printf("%s",dest);
return 0;
}
答:
⽅法1:⼀共有4个错误;
int main()
{
char* src = "hello,world";
int len = strlen(src);
char* dest = (char*)malloc(len+1);//要为分配⼀个空间 char* d = dest; char* s = &src[len-1]; //指向最后⼀个字符
while( len-- != 0 )
*d++=*s--;
*d = 0; //尾部要加’\0’
printf("%sn",dest);
free(dest); // 使⽤完,应当释放空间,以免造成内存汇泄露
dest = NULL; //防⽌产⽣野指针
return 0;
}
⽅法2: (⽅法⼀需要额外的存储空间,效率不⾼.) 不错的想法
#include <stdio.h>
#include <string.h>
main()
{
char str[]="hello,world";
int len=strlen(str);
char t;
for(int i=0; i<len/2; i++)
{
t=str[i];
str[i]=str[len-i-1]; //⼩⼼⼀点
str[len-i-1]=t;
}
printf("%s",str);
return 0;
}
3.对于⼀个频繁使⽤的短⼩函数,在C语⾔中应⽤什么实现,在C++中应⽤什么实现?
c⽤宏定义,c++⽤inline
4. unsigned char *p1;
unsigned long *p2;
sizeof 指针p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;
请问p1+5= ;
p2+5= ;
答案:0x801005(相当于加上5位) 0x810014(相当于加上20位);
5.进程和线程的差别。
答:线程是指进程内的⼀个执⾏单元,也是进程内的可调度实体.
与进程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执⾏,同⼀个进程的多个线程之间也可并发执⾏
(3)拥有资源:进程是拥有资源的⼀个独⽴单位,线程不拥有系统资源,但可以访问⾪属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显⼤于创建或撤消线程时的开销6.⽤宏定义写出swap(x,y)
答#define swap(x, y)
x = x + y;
y = x - y;
x = x - y;
7.数组a[N],存放了1⾄N-1个数,其中某个数重复⼀次。写⼀个函数,出被重复的数字.时间复杂度必须为o(N)函数原型:int do_dup(int a[],int N)
答:int do_dup(int a[],int N) //未经调试
{
int sun = 0;
int sum2;
for(int i=0;i<N;++i)
{
Sum+=a[i];
}
Sum2 = (1+N-1)*N/2;
Return (sum-sum2);
}
8.下述三个有什么区别?
char * const p;
char const * p
const char *p
解答:
char * const p; //常量指针,p的值不可以修改
char const * p;//指向常量的指针,指向的常量值不可以改
const char *p; //和char const *p
9… 以下代码中的两个sizeof⽤法有问题吗?[C易]
void UpperCase( char str[] ) // 将 str 中的⼩写字母转换成⼤写字母
{
for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i )
if( 'a'<=str[i] && str[i]<='z' )
str[i] -= ('a'-'A' );
}
char str[] = "aBcDe";
cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;
答:函数内的sizeof有问题。根据语法,sizeof如⽤于数组,只能测出静态数组的⼤⼩,⽆法检测动态分配的或外部数组⼤⼩。函数外的str是⼀个静态定义的数组,因此其⼤⼩为6,函数内的str实际只是⼀个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作⽤于上 只将其当指针看,⼀个指针为4个字节,因此返回4。
注意:数组名作为函数参数时,退化为指针.
数组名作为sizeof()参数时,数组名不退化,因为sizeof不是函数.
10.⼀个32位的机器,该机器的指针是多少位
指针是多少位只要看地址总线的位数就⾏了。80386以后的机⼦都是32的数据总线。所以指针的位数就是4个字节了。
指出下⾯代码的输出,并解释为什么。(不错,对地址掌握的深⼊挖潜)
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a+1);
printf("%d,%d",(a+1),(ptr-1));
}
输出:2,5
(a+1)就是a[1],(ptr-1)就是a[4],执⾏结果是2,5
&a+1不是⾸地址+1,系统会认为加⼀个a数组的偏移,是偏移了⼀个数组的⼤⼩(本例是5个int)
int *ptr=(int *)(&a+1);
则ptr实际是&(a[5]),也就是a+5
原因如下:
&a是数组指针,其类型为 int (*)[5];
⽽指针加1要根据指针类型加上⼀定的值,
不同类型的指针+1之后增加的⼤⼩不同
a是长度为5的int数组指针,所以要加 5*sizeof(int)
所以ptr实际是a[5]
但是prt与(&a+1)类型是不⼀样的(这点很重要)
所以prt-1只会减去sizeof(int*)
a,&a的地址是⼀样的,但意思不⼀样,a是数组⾸地址,也就是a[0]的地址,&a是对象(数组)⾸地址,a+1是数组下⼀元素的地址,即a[1],&a+1是下⼀个对象的地址,即a[5].
11.引⽤:平级内解决交换问题,不开辟多余空间
void swap(char* &p,char *& q)
{
char *t = p;
p=q;
q=t;
}
int main()
{
char *p = china;
char *q = ame;
swap(p,q);
return 0;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论