面试准备

本文列举了一系列C语言面试中常见的试题,涉及字符串处理、指针、数组、内存管理、数据结构等多个方面。试题涵盖strcpy可能导致的数组越界、strcpy的工作方式、strlen的计算方式等知识点,并强调了内存安全和理解基本概念的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

改错:

试题1:

void test1()
{
 char string[10];
 char* str1 = "0123456789";
 strcpy( string, str1 );
}


  试题2:

void test2()
{
 char string[10], str1[10];
 int i;
 for(i=0; i<10; i++)
 {
  str1[i] = 'a';
 }
 strcpy( string, str1 );
}


  试题3:

void test3(char* str1)
{
 char string[10];
 if( strlen( str1 ) <= 10 )
 {
  strcpy( string, str1 );
 }
}


试题1字符串str1需要11个字节才能存放下(包括末尾的’/0’),而string只有10个字节的空间,strcpy会导致数组越界;

  对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;

第一个参数表示目的字符串,第二个参数表示源字符串。但是需要注意的就是第二个字符指针必须指向一个字符串,而不能是一个字符数组

  对试题3,if(strlen(str1) <= 10)应改为if(strlen(str1) < 10),因为strlen的结果未统计’/0’所占用的1个字节。

试题4:

void GetMemory( char *p )
{
 p = (char *) malloc( 100 );
}

void Test( void ) 
{
 char *str = NULL;
 GetMemory( str ); 
 strcpy( str, "hello world" );
 printf( str );
}
试题4传入中GetMemory( char *p )函数的形参为字符串指针,在 函数内部修改形参并不能真正的改变传入形参的值 ,执行完

执行完

char *str = NULL;
GetMemory( str );
 后的str仍然为NULL


试题5:

char *GetMemory( void )

 char p[] = "hello world"; 
 return p; 
}

void Test( void )

 char *str = NULL; 
 str = GetMemory(); 
 printf( str ); 
}
p指向的内存空间已经在退出函数时变成无效内存了


试题6:

void GetMemory( char **p, int num )
{
 *p = (char *) malloc( num );
}

void Test( void )
{
 char *str = NULL;
 GetMemory( &str, 100 );
 strcpy( str, "hello" ); 
 printf( str ); 
}

后未判断内存是否申请成功,应加上:

if ( *p == NULL )
{
 ...//进行申请内存失败处理
}

试题7:

void Test( void )
{
 char *str = (char *) malloc( 100 );
 strcpy( str, "hello" );
 free( str ); 
 ... //省略的其它语句
}

后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个“野”指针,应加上:

str = NULL;
2.内功题 
 
试题1:分别给出BOOL ,int ,float,指针变量 与“零
值”比较的 if 语句(假设变量名为var ) 
 
  解答: 
 
    BOOL 型变量:if(!var) 
 
    int 型变量: if(var==0) 
 
   float型变量: 
 
   const float EPSINON = 0.00001; 
 
   if ((x >= - EPSINON) && (x <= EPSINON) 
 
   指针变量:  if(var==NULL) 

试题2:以下为Windows NT下的32位C++程序,请计算
sizeof 的值 
void Func ( char str[100] ) 

 sizeof( str ) = ? 

 
void *p = malloc( 100 ); 
sizeof ( p ) = ?
 
  解答: 
 
sizeof( str ) = 4 

sizeof ( p ) = 4

Func ( char str[100] )函数中数组名作为函数形参时,
在函数体内,数组名失去了本身的内涵,仅仅只是一个指针

Windows NT 32位平台下,指针的长度(占用内存的大
小)为4字节,故sizeof( str ) 、sizeof ( p )  都为4


4. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
这个问题用几个解决方案。我首选的方案是:
while(1) { } 
一些程序员更喜欢如下方案:
for(;;) { } 
这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如
果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们
这样做的
基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过
为什么。”这会给我留下一个坏印象。
第三个方案是用goto 
Loop: 
... 
goto Loop; 

7. 引用与指针有什么区别? 
1) 引用必须被初始化,指针不必。 
2) 引用初始化以后不能被改变,指针可以改变所指的对象。 
2) 不存在指向空值的引用,但是存在指向空值的指针

C语言可执行代码结构


 名称 内容
代码段  可执行代码、字符串常量
数据段  已初始化全局变量、已初始化全局静态变量、局部静态变量、常量数据
BSS段  未初始化全局变量,未初始化全局静态变量
 局部变量、函数参数
 动态内存分配


extern可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中



 
 
void *memset(void *s, char ch,  size_t n);
函数解释: 将s中前n个字节 (typedef unsigned int size_t)用 ch 替换并返回 s


void*和C结构体

问:你能设计一个能接受任何类型的参数并返回interger(整数)结果的函数吗?

答:如下:

 
 
  1. int func(void *ptr) 


下面的代码段有错,你能指出来吗?

 
 
  1. #include<stdio.h> 
  2.  
  3. int main(void
  4.     char *ptr = "Linux"
  5.     *ptr = 'T'
  6.  
  7.     printf("\n [%s] \n", ptr); 
  8.  
  9.     return 0; 

答:这是因为,通过*ptr = ‘T’,会改变内存中代码段(只读代码)“Linux”的第一个字母。这个操作是无效的,因此会造成seg-fault或者崩溃

6、请写出下列代码的输出内容 
#include<stdio.h> 
main() 

int a,b,c,d; 
a=10; 
b=a++; 
c=++a; 
d=10*a++; 
printf("b,c,d:%d,%d,%d",b,c,d); 
return 0; 

答:10,12,120 


static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?
static函数与普通函数有什么区别?

static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元
中被引用; 
static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结
果值; 
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一
份拷贝 



进程和线程的差别。 

  线程是指进程内的一个执行单元,也是进程内的可调度实体. 

  与进程的区别: 

  (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位 
  (2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行 
  (3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源. 
  (4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销


找错

int main(){ 
char* src = "hello,world"; 
int len = strlen(src); 
char* dest = (char*)malloc(len+1);//要为\0分配一个空间 
char* d = dest; 
char* s = &src[len-1];//指向最后一个字符 
while( len-- != 0 ) 
*d++=*s--; 
*d = 0;//尾部要加\0 
printf("%s\n",dest); 
free(dest);// 使用完,应当释放空间,以免造成内存汇泄露 
return 0; 


 
 
  1. #include<stdio.h> 
  2.  
  3. int main(void
  4.     int a = 10, b = 20, c = 30; 
  5.     printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2)); 
  6.  
  7.     return 0; 

答:输出结果是:

 
 
  1. 110..40..60 


全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么? 
答:可以,在不同的C文件中以static形式来声明同名全局变量

1. 队列和栈有什么区别? 
队列先进先出,栈后进先出


设有以下说明和定义: 
typedef union {long i; int k[5]; char c;} DATE; 
struct data { int cat; DATE cow; double dog;} too; 
DATE max; 
则语句 printf("%d",sizeof(struct date)+sizeof(max));的执行结果是:___52____ 
答:DATE是一个union, 变量公用空间里面最大的变量类型是int[5], 占用20个字节所以它的大小是20 
data是一个struct, 每个变量分开占用空间依次为int4 + DATE20 + double8 = 32
所以结果是 20 + 32 = 52. 


strlen用来求字符串的长度用的
而sizeof是用来求指定变量或者变量类型等所占内存大小用的
比如strlen("nihao")它的结果是5
而sizeof(int)它的结果是2也就是说int型占两个字节
 
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
&a + 1是对整个数组进行操作

嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa55。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。 这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:     int *ptr;     ptr = (int *)0x67a9;

    *ptr = 0xaa55;

下面的代码片段的输出是什么,为什么? char *ptr; if ((ptr = (char *)malloc(0)) == NULL)     puts("Got a null pointer"); else     puts("Got a valid pointer"); 这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是"Got a valid pointer"

malloc(0)的时候堆上已经不能使用,但是处发了内存保护机制,用内存的碎片来分配

13.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中?

答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理
堆: 程序运行时动态申请,new 和 malloc申请的内存就在堆上


10.数组和链表的区别
数组:数据顺序存储,固定大小
连表:数据可以随机存储,大小可动态改变



3、 如何初始化一个指针数组。 
首先明确一个概念,就是指向数组的指针,和存放指针的数组。 
指向数组的指针:char (*array)[5];含义是一个指向存放5个字符的数组的指针。 
存放指针的数组:char *array[5];含义是一个数组中存放了5个指向字符型数据的指针



const int *p;指针所指的对象为常量
int const *p;指针所指的对象为常量
int * const p  指针本身是常量

沿着*号划一条线,如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量



strlen和sizeof的区别

char str[20]="0123456789"; 
int a=strlen(str); //a=10; 
int b=sizeof(str); //而b=20;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值