C++常见难点笔试面试题

C++常见难点笔试面试题

跨行加⭐⭐⭐⭐⭐

main()
{
	//例子[1]
    int a[5]={1,2,3,4,5};
    int *ptr=(int *)(&a+1);//&a相当于变成了行指针,加1则变成了下一行首地址
    printf("%d,%d,%d",*(a+1),*(ptr-1));
    //例子[2]
    int * ptr1 = (int *)( (int)a + 1);
    int * ptr2 = (int *)( (int)a + 4);
    printf("%d,%d\n", ptr[-1],*ptr2);
}
例子一
1. *(a+1)就是a[1],执行结果是2
	因为a是int*类型,a+1步长为4
2.*(ptr-1)就是a[4],结果为5
    首先我们得到的是&a的地址,而&a是一个含有5int类型的数组,所以&a+1的步长就是a数组整个的大小,加到a数组的末尾后面,
    (int *)(&a+1)这一句话,把它转换成int *类型的指针,步长又为4了,后面给它-1,即*(ptr-1) 相当于减了一个int* 的步长,结果为5

例子二
首先看里面的语句  (int)a + 1(int)a + 4
这个意思是我们把a的地址得到,然后把a的地址+1+4,
那么ptr1肯定是一个乱的值,因为取的是不对的地址
而ptr2得到的是数组第二个元素的地址,再转换成(int *)类型
这样我们又可以进行后续的+-操作进行指针的引用了。

如何写出可重入的函数?⭐⭐⭐⭐⭐

满足下列条件的函数多数是不可重入的:也可以这样理解,重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括 static),这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。如果确实需要访问全局变量(包括 static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量付出一些性能代价。
(1)函数体内使用了静态的数据结构;

(2)函数体内调用了malloc()或者free()函数;

(3)函数体内调用了标准I/O函数。

pragma pack(n)的作用

总长度可以被n整除,成员变量对其位置可以被min(n,自身大小)整除

#pragma pack(1)
struct node {
	char f;
	double e;
	short  a;
};
sizeof1+8+2=11

#pragma pack(4)
struct node {
	char f;
	double e;
	short  a;
};
sizeof16


struct node {
	char f;
	double e;
	short  a;
};
sizeof24

中断是嵌入式系统中重要的组成部分

中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。
具代表性的是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt void compute_area (void)
{
  double area = PI * radius * radius;
  printf(" Area = %f", area);
  return area;
}
ISR不可能有参数和返回值的!
ISR尽量不要使用浮点数处理程序,浮点数的处理程序一般来说是不可重入的,而且是消耗大量CPU时间的!!
printf函数一般也是不可重入的,UART属于低速设备,printf函数同样面临大量消耗CPU时间的问题!

typedef 和#define

typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。
例如,思考一下下面的例子:
  #define dPS struct s *
  typedef struct s * tPS;
  
  以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
  这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
  dPS p1,p2;
  tPS p3,p4;
  
  第一个扩展为
  struct s * p1, p2;
  
  上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。

RAM和ROM

ROM是只读存储器,掉电不丢失
RAM是读写存储器,掉电丢失
SRAM:CPU的缓存就是SRAM,静态的随机存取存储器,加电情况下,不需要刷新,数据不会丢失
DRAM,动态随机存取存储器最为常见的系统内存,需要不断刷新,才能保存数据

关键字static的作用是什么

static用来修饰一个局部的变量的时候,
生命域是全局的
作用域是局部的

static用来修饰一个模块内的(某一个C的源程序文件)全局变量的时候
生命域不变
作用域减小,只在本模块内有效

static用来修饰一个函数的时候
作用域减小,只在本模块内有效

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

 请问运行Test函数会有什么样的结果?
 答:程序崩溃。因为GetMemory并不能传递动态内存,Test函数中的 str一直都是 NULLstrcpy(str, "hello world");将使程序崩溃。

char *GetMemory(void)
 { 
  char p[] = "hello world";
  return p;
 }
 void Test(void)
 {
  char *str = NULL;
  str = GetMemory(); 
  printf(str);
 }
 请问运行Test函数会有什么样的结果?
 答:可能是乱码。因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,
 但其原现的内容已经被清除,新内容不可知。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值