C语言常见面试题汇总 您所在的位置:网站首页 广电技术中心面试问题汇总 C语言常见面试题汇总

C语言常见面试题汇总

2024-07-10 11:57| 来源: 网络整理| 查看: 265

目录 题1:变量的声明和定义有什么区别题2:写出bool 、int、 float、指针变量与“零值”比较的if语句题3:sizeof和strlen的区别题4:C中的malloc和C++中的new有什么区别题5:说明关键字volatile有什么含意题6:写一个“标准”宏MIN题7:设置地址为0x67a9的整型变量的值为0xaa66题8:链表和数组有什么区别题9:用变量a定义题10:引用和指针的区别题11:static的用法(定义和用途)题12:const的用法(定义和用途)题13:内存四区题14:大小端问题题15:静态局部变量在什么时候分配内存题16:什么是不可重入函数和可重入函数题17:#define宏定义与typedef的区别值传递改变值这类问题计算sizeof的值计算strlen的值char str[]和char *str数组作为函数参数传递数组指针和指针数组的问题\*p++、 (\*p)++、 \*++p、 ++\*pconst 二级指针

题1:变量的声明和定义有什么区别

为变量分配地址和存储空间的称为定义,不分配地址的称为声明。 一个变量可以在多个地方声明,但是只在一个地方定义。 加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。

题2:写出bool 、int、 float、指针变量与“零值”比较的if语句

bool型数据: if( flag ) { A; } else { B; }

int型数据: if( 0 != flag ) { A; } else { B; }

指针型数: if( NULL == flag ) { A; } else { B; }

float型数据: const float EPSINON = 0.000001; if (( flag >= -EPSINON ) && ( x int i = 0x12345678; char *cp = (char *)&i; if(*cp == 0x78) printf("little endian"); else printf("big endian\n"); }

方法二:

void checkCpuMode(void) { int a = 0x12345678; if((char)a == 0x12) printf("big endian\n"); else printf("little endian\n"); }

方法三:

void checkCpuMode(void) { union { short s; char c[sizeof(short)]; }un; un.s=0x0102; if(un.[0]==1&&un.c[1]==2) printf("big endian\n"); else printf("little endian\n"); } 题15:静态局部变量在什么时候分配内存

1、 ① static局部变量在编译阶段就已经分配内存空间了,也就是函数没有调用前它就已经存在了。 ② 普通局部变量只有运行到定义该变量的时候才会分配内存空间。 2、 ① 当执行完定义该static局部变量的函数体后,该static变量的内存空间不会被释放,只有程序结束时static变量才会自动释放。 ② 当执行完定义该普通局部变量的函数体后,该普通局部变量的内存空间就会被释放。 3、 ① 如果static局部变量不初始化,那么它默认为0。 ② 如果普通局部变量不初始化,那么它的值为随机数。 4、 ① static局部变量的初始化语句只会执行一次,下次再运行该初始化语句就不会被初始化,但是它可以被多次赋值。 ② 每次运行该普通局部变量的定义时该变量都会被初始化。

题16:什么是不可重入函数和可重入函数

不可重入函数: 不能由超过一个任务所共享。不可以在它还没有返回就再次被调用。例如printf,malloc,free等都是不可重入函数。 可重入函数可以由多个任务并发使用,而不必担心数据错误。可重入函数是在运行期间被打断,而他的打断者又调用了它本身的情况下,不会产生不可预期的运行结果的函数。 【可重入函数】 不为连续的调用持有静态数据 不返回指向静态数据的指针,所有数据都由函数的调用者提供 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据 如果必须访问全局变量,记住利用互斥信号量来保护全局变量 绝不在函数内调用任何不可重入函数 【不可重入函数】 函数中使用了静态变量,无论是全局变量还是局部静态变量 函数返回静态变量 函数中调用了不可重入函数 函数体内使用了静态的数据结构 函数体内调用了malloc()或者free()函数 函数体内调用了其他标准I/O函数 总得来说,如果一个函数在重入条件下使用了未受保护的共享资源,那么他就是不可重入的

题17:#define宏定义与typedef的区别

#define宏定义是字符替换,typedef是定义类型,是声明一种新的类型,等同自带的基本类型。

#define是宏,处理的时候位于编译前阶段,宏处理器基本上对你的C/C++程序不会有任何的感知。它只处理宏的语法。而编译阶段的“程序”得到的是宏处理完的结果。

typedef是编译阶段的一部分。它的意义是单一的。

宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时处理的,它不是作简单的代换,而是对类型说明符进行重新命令。被命名的标识符具有类型定义说明的功能。

#include #define PIN1 char* typedef char* PIN2; void main() { //使用#define相当于:char* x, y;就是说x是char指针类型,而y是char类型,如果要连续定义两个指针需要写成char *x, *y; PIN1 x, y; //使用typedef相当于:char* x, char* y;就是说x是char指针类型,而y也是char指针类型 PIN2 a, b; printf("By #define :%d %d\n\n",sizeof(x), sizeof(y)); printf("By typedef :%d %d\n\n", sizeof(a), sizeof(b)); //system("pause"); return 0; }

在这里插入图片描述

值传递改变值这类问题

下面的代码有什么问题?

void GetMem(char *p) { p = (char*)malloc(100); } void main() { char *str = NULL; GetMem(str); strcpy(str, "hello word!"); printf(str); }

分析:

程序崩溃。在上面已经分析过了,传递给GetMem函数形参的只是一个副本,修改形参p的地址对实参str丝毫没有影响。所以str还是那个str,仍为NULL,这时将字符串常量拷贝到一个空地址,必然引发程序崩溃。下面的方法可以解决这个问题:

void GetMem(char **p) { *p = (char*)malloc(100); } void main() { char *str = NULL; GetMem(&str); strcpy(str, "hello word!"); printf(str); free(str); //不free会引起内存泄漏 }

看似有点晦涩,其实很好理解。本质上是让指针变量str指向新malloc内存的首地址,也就是把该首地址赋值给指针变量str。前面我们说过,指针传递本质上也是值传递,要想在子函数修改str的值,必须要传递指向str的指针(str本身就是指针,指针的指针是二级指针),因此子函数要传递的是str的地址,这样通过指针方式修改str的值,将malloc的内存首地址赋值给str。

计算sizeof的值 char str1[] = {'a', 'b', 'c', 'd', 'e'}; char str2[] = "abcde"; char *ptr = "abcde"; char book[][80]={"计算机应用基础","C语言","C++程序设计","数据结构"};

sizeof(str1)=?

sizeof(str2)=?

sizeof(ptr)=?

sizeof(book)=?

sizeof(book[0])=?

分析:

sizeof(str1)=5,就是5*sizeof(char)=5;

sizeof(str2)=6,字符串都是以’0’结尾,所以所占字节数为6;

sizeof(ptr)=4,ptr是一个指针,在32位平台上大小为4字节;

sizeof(book)=320,book是一个二维数组,4*80*1

sizeof(book[0])=80,book[0]是第一维数组,因为此80*1

根据sizeof求数组元素的个数也很简单,拿第一个来说,就是sizeof(str1)/sizeof(char)。

计算strlen的值 char arryA[] = {'a','b','c',0,'d','e'}; char arryB[] = {'a','b','c','d','e'}; char arryC[6] = {'a','b','c','d','e'}; char *str = "abcde";

分析:

strlen(arryA) = 3,strlen遇到’\0’就会返回,无论后面有多少个字符;

strlen(arryB)长度无法确定,没有人为写入‘\0’,strlen会继续计算直到找到结束符,结果未知;

strlen(arryC)=5,指定了数组大小,编译器会自动在空余地方添加’\0’,这其实跟char arryC[6] = {‘a’,‘b’,‘c’,‘d’,‘e’,‘\0’};等价。

strlen(str) = 5,不包括结尾的’\0’。

char str[]和char *str

1)下面的操作合法么?出错的话,会是在那个阶段?编译时期还是运行时期?

char str[] = "hello"; str[0] = 's'; //合法么 char *str = "hello"; str[0] = 's'; //合法么

分析:

这两个都可以成功编译,只是第二个会在运行时期出现段错误。下面来分析一下:

首先"hello"是一个字符串常量,存储在静态数据区域(data段),这是在编译时期就确定的。第一个是将字符串常量赋值给了一个变量(全局变量在数据段,局部变量在栈区),实际上是将字符串常量拷贝到了变量内存中,因此修改的只是str[]这个变量的值。

第二个是将字符串常量的首地址赋值给指针str,对指针str操作就是对字符串常量进行修改!因此出现了段错误。

(2)理解了上面的知识,判断一下下面的true or false?

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


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有