嵌入式C语言

1.预处理加入#error的目的是什么?

只要遇到#error就会跳出一个编译错误,其目的就是保证程序按照你所想的那样进行编译。

2.宏定义1年中有多少秒?

#define     SECOND_PER_YEAR				(60*60*24*365)UL

3.程序编译过程

预处理----编译----汇编----链接

4.写一个标准宏,这个宏返回两个参数较小的一个

#define		MIN(A,B)					((A)>=(B)?(B):(A))

5.不能做switch()的参数类型

实型,具体如下:
支持类型:byte,char,short,int,long,bool,枚举型
不支持类型:float,double,string

6.如何判断一段程序是由C程序还是C++程序编译的

#ifdef				__caplusplus
	printf("C++");
#else
	printf("C");

7.分别写出bool,int,float,指针类型的变量与零比较的语句

bool:

if(!a)
if(a)

int:

if(0 == a)

float:

const float EXP = 0.000001;
if((a >= -EXP) && (a <= EXP))

指针:

if(a != NULL)
if(a == NULL)

8.什么叫野指针,产生原因,如何规避

野指针就是指针指向的位置是未知的
原因:
1.指针变量未初始化
2.指针释放后未置空
3.指针操作时越界访问
规避:
1.初始化时置NULL
2.释放时置NULL

9.引用和指针的区别

1.引用必须被初始化,指针不必
2.引用初始化后不能被改变,指针可以改变所指对象
3.不存在指向空值的引用,但是存在指向空值的指针
4.++不同,指针是地址自增,引用是对象自增
5.引用的本质是指针常量

10.头文件中#include "stdio.h"与#include <stdio.h>的区别

前者从当前工作路径寻找stdio.h如果找不到编译器会在系统文件目录下查找
后者直接从系统文件目录下查找。

11.头文件中的#ifndef / #define / #enif的作用

防止头文件被重复引用

12.sizeof和strlen的区别

1.sizeof是一个操作符,strlen是库函数
2.sizeof的参数可以是数据的类型,也可以是变量,而strlen只能以结尾为’/0’的字符串作为参数
3.编译器在编译的时就计算处了sizeof的结果。而strlen函数必须在运行时才能计算出来,并且sizeof计算的时数据占内存的大小,而strlen计算的是字符串的实际长度。

13.一个指针可以是volatile吗?

可以,因为指针和普通变量一样,有时也有变化程序的不可控性。常见例:中断服务程序修改一个指向buff的指针时,必须用volatile来修饰

14.malloc与calloc的区别

1.参数个数的区别:malloc(size_t size)函数有一个参数,即要分配的内存空间的大小。calloc(size_t numElements,size_t sizeOfElement)有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配内存空间的大小。
2.初始化内存的区别:malloc不能初始化所分配的内存空间,在动态分配完内存后,里面的数据室随机的,calloc能初始化所分配的内存空间,在动态分配完内存后,自动初始化内存空间为0。
为什么多用malloc而很少用calloc?
因为calloc虽然对内存进行了初始化(全部初始化为0),但是同样也要降低效率的
calloc相当于
p = malloc();
memset(p, 0,size);
多了对内存的写零操作,而写零这个操作我们有时候需要,而大部分时间不需要。

15.用变量a给出下面定义

a)一个整型数?
b)一个指向整型数的指针?
c)一个指向指针的指针,它指向的指针是指向一个整数?
d)一个有10个整形数的数组?
e)一个指向10个指针的数组,该指针指向一个整型数的?
f)一个指向有10个整型数数组的指针?
g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数?
h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数,并返回一个整型值?

a) int a;
b) int *a;
c) int **a;
d) int a[10];
e) int *a[10];
f) int (*a)[10];
g) int (*a)(int );
h) int (*a[10])(int );

16.关键字static的作用是什么?

1.修饰局部变量,函数调用时局部变量只初始化一次,下次调用中维持上次的值。(改变生存周期)。
2.修饰全局变量,全局变量仅在本文件可用,其他文件不可用。(改变作用域)。
3.修饰函数时,函数仅在本文件可用,其他文件不可用。(改变作用域)。

17.简述strcpy,sprintf,memcpy的区别

1.操作对象不同,strcpy的两个对象均为字符串,sprintf的操作源对象可以是多种数据类型,目的操作对象师字符串,memcpy的两个对象就是两个可操作的内存地址,并不限于何种数据类型。
2.执行效率不同,memcpy最高,strcpy次之,sprintf的效率最低。
3.实现功能不同,strcpy主要实现字符串变量间的拷贝,但是针对对象不同,根据实际需求,来选择合适的函数实现拷贝功能。

18.设置地址0x67a9的整型变量的值为0xaa66

int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa66;

19. 编写算法实现char *strcpy(char * dest,const char src),并解释为什么要返回char?

char *strcpy(char *dst,const char *src)
{
	assert(dst != NULL && src != NULL);
	char *ret = dst;
	while((*dst++ = *src++) != '\0');
	return ret;

返回dst的原始值使函数能够支持链式表达式。

20.什么是大小端,写一个简单的程序判断系统的大小端。

小端:低字节存储在低地址,高字节存储在高地址。
大端:高字节存储在低地址,低字节存储在高地址。

union
{
	int a;
	char b;
}test;
int main()
{
	test.a = 0x01;
	if( test.b )
	printf("little endian");
	else
	printf("big endian");

21.const的使用

const int a;    //定义一个整型常量
int const a;    //定义一个整型常量
const int *a;   //定义一个常量指针,指针可变,指向常量
int *const a;	//定义一个指针常量,指针为常量,指向变量
int const * const a;	//定义一个指针为常量,指向常量

22.关键字volatile的作用以及常用场合

告诉编译器不要随便优化我的代码,在用到这个变量时必须每次都小心重新读取这个变量的值,而不是使用保存在寄存器的备份。
常用场合:

一个硬件寄存器
中断中用到的变量
线程之间共享变量

23.宏和函数的优缺点?

1.函数调用时,先求出实参表达式的值,然后带入形参。而使用参数的宏只是简单进行字符替换。
2.函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则时在编译时进行的,在展开时不分配内存单元,不进行值的传递处理,也没有”返回值“的概念。
3.对函数中的实参和形参都要定义类型,二者的类型要求一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的参数也是无类型,只是一个符号的代表,展开时带入指定的字符即可。宏定义时,字符串可以是任何类型的数据。
4.使用的宏次数多时,程序展开后,源程序过长,每一次展开都使程序增长,而函数调元不使源程序变长。
5.宏替换不占运行时间,只占编译时间;而函数调用则占运行时间(分配单元,保留现场,值传递,返回)。

24.已知一个数组table,用一个宏定义,求出数组的元素个数?

#define		NTBL(table)		(sizeof(table)/sizeof(table[0]))

25.局部变量能否和全局变量重名?

能,局部变量会屏蔽全局变量。

26.交换两个变量的值,不使用第三个变量。即a = 3,b = 5,交换之后a = 5,b = 3;

a = a+b;
b = a - b;
a = a - b;

或者:

a = a ^ b;
b = a ^ b;
a = a ^ b;

27.指针的指针

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

这段代码是错误的,试图修改指针的值,只能传递指针的地址。

28.void类型指针

指针有两个属性:指向变量/对象的地址和长度,单指针值存储地址,长度取决于指针的类型,编译器根据指针的类型从指针指向的地址向后寻址,指针类型不同,寻址范围不同。比如:

int类型 从指定地址向后寻找4字节作为变量的存储单元
double类型 从指定地址向后寻找8字节作为变量的存储单元
void 即“无类型”,void *则为无类型指针,可以指向任何数据类型。
总结:指针的类型决定指针+1向后走多少步,void类型可以指向任意类型的数据,即可用任意类型的数据对void指针赋值。

29.const,volatile可以同时修饰一个变量吗?

可以,只读寄存器,const修饰是系统程序不应该试图去修改它。volatile告诉编译器,它是随时可能变化的,每次用它都必须重新获取。

30.程序的内存分配

1.栈区(stack)由编译器自动分配和释放,存放函数的参数值,局部变量等。
2.堆区(heap)一般由程序员分配和释放。分配使用new和malloc,释放使用deleted和free。
3.静态区(全局区)全局变量和静态变量是存放在一块的,初始化的在一块区域,未初始化存放在另一块区域(BSS)。
4.常量区 存放常量字符串。
5.程序代码区 存放函数的二进制代码。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值