嵌入式工程师 面试题 集-C语言

2023-05-16

预编译

1.什么是预编译,何时需要预编译

答:预编译又称预处理 , 就是做些代码文本的替换工作。# 开头的指令,比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。
C提供的预处理功能主要有以下三种:
1 )宏定义。#define
2 )文件包含。#include。该指令指示编译器将xxx.xxx文件的全部内容插入此处。
3 )条件编译。#ifdef/#ifndef, #endif, #if/#else

何时需要预编译:
1 )总是使用不经常改动的大型代码体。
2 )程序由多个模块组成,所有模块使用一组标准的包含文件和相同的编译选项。

2.高级语言源程序生成机器代码的过程

预处理 ——> 编译 ——> 汇编 ——> 链接

预处理:在高级语言源程序中插入所有用#include命令指定的文件和用#define声明指定的宏。

编译:将预处理后的源程序文件编译生成相应的汇编语言程序。

汇编:由汇编程序将汇编语言源程序文件转换为可重定位的机器语言目标代码文件。

链接:由链接器将多个可重定位的机器语言目标文件以及库例程(如printf()库函数)链接起来,生成最终的可执行目标文件(机器码)。

3.#include <file.h> #include “file.h”的区别?

答:前者从标准库路径寻找file.h;
后者从当前工作路径寻找file.h。

4..h头文件中的ifndef/define/endif 的作用?

答:防止该头文件被重复引用。

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

答:

#ifdef __cplusplus
    printf(“c++”);
#else
    printf(“c”);
#endif

6.预处理器标识#error的目的是什么?

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

宏定义

1.用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)。

答:#define SECONDS_PER_YEAR    (60 * 60 * 24 * 365)UL

2.交换两个参数值的“标准”宏.

答:#define SWAP(a,b)    (a)=(a)+(b); (b)=(a)-(b); (a)=(a)-(b)

3.写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。

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

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

答:#define NTBL(tab)    (sizeof(tab) / sizeof(tab[0]))

5.嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置 a 的 bit3,第二个清除 a 的bit3。在以上两个操作中,要保持其它位不变。

答:

    #define BITS_CLR(v, n)      v &= ~(1u<<n)
    #define BITS_SET(v, n)      v |= (1u<<n)

    static int a;

    BTIS_SET(a, 3);
    BTIS_CLR(a, 3);

6.带参数的 宏 与 函数 的优缺点

答:

带参宏优点

1)参数不存类型转换和运算问题,因为带参的宏只是替换;

2)不占用运行时间(无内存、现场保护、值传递、返回等)

缺点

1)宏使用次数多,程序增加很多;

2)占编译时间

带参函数优点

1)函数调用次数多,程序增加很少;

2)不占编译时间

缺点

1)参数存在类型转换和运算问题;

2)调用占运行时间(分配内存、现场保护、值传递、返回)

7.Typedef作用:

答:为 数据类型 取 别名

8.typedef,#define 定义数据类型,两者有什么不同?哪一种更好一点?

答:typedef要比#define要好,特别是在有指针的场合。请看例子:

typedef char* pStr1;
#define pStr2 char*
pStr1 s1, s2;
pStr2 s3, s4;

在上述的变量定义中,s1、s2、s3都被定义为char *,而s4则定义成了char,不是我们所预期的指针变量,根本原因就在于#define只是简单的字符串替换而typedef则是为一个类型起新名字。上例中define语句必须写成 pStr2 s3, *s4; 这这样才能正常执行。

选择与循环结构

1.嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?

答:

while(1) //方案1
{
    ;
}
for( ;1 ;) //方案2
{
    ;
}
Loop:
…
goto Loop; //方案3

2.do……whilewhile……有什么区别?

答:前一个循环一遍再判断,后一个判断以后再循环。

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

答:实型

指针 与 数组

1.用变量a给出下面的定义

a) 一个整型数(Aninteger)?
b) 一个指向整型数的指针(Apointer to an integer)?
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)?
d) 一个有10个整型数的数组(An array of 10 integers)?
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)?
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)?
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument andreturns an integer)?
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argumentand return an integer )
答:

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 );

2.指向字符串常量的指针,指向字符串的常量指针(const)

答:

const char* p = "hello"; //指向 "字符串常量"
p[0] = 'X'; //错误! 想要修改字符串的第一个字符. 但是常量不允许修改
p = p2; //正确! 让p指向另外一个指针.
char* const p = "hello"; //指向字符串的" 常量的指针"
p[0] = 'X'; //正确! 允许修改字符串, 因为该字符串不是常量
p = p2; //错误! 指针是常量, 不许修改p的指向

char const * 和 const char* 是一样的. const 的位置在char左边还是右边都一样.
常量指针的const应当写在 *星号的右边.
指向常量字符串的常量指针的写法是 const char* const p = "xx"; 要2个const

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

答:野指针就是 指针指向的位置是不可知的。
原因:
1、指针变量未初始化
2、指针释放后之后未置空(指针所指向的变量 在指针之前被销毁)
3、指针操作超越变量作用域
规避:
1、初始化时置 NULL
2、释放时置 NULL

4.简述数组与指针的区别?

答:
数组 在静态存储区被创建(如全局数组),或 在栈上被创建。
指针 可以随时指向任意类型的内存块。
(1)修改内容上的差别

    char a[] = “hello”;
    a[0] = ‘X’;
    char *p = “world”; // 注意p 指向常量字符串
    p[0] = ‘X’; // 编译器不能发现该错误,运行时错误

(2) 用运算符sizeof 可以计算出数组的容量(字节数)。sizeof(p), p 为指针得到的是一个 指针变量的字节数,而不是p所指的内存容量。C++/C 语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。

    char a[] = “hello world”;
    char *p = a;
    printf("%d\r\n", sizeof(a)); // 12 字节
    printf("%d\r\n", sizeof(p)); // 4 字节
计算数组和指针的内存容量
    void Func(char a[100])
    {
        printf("%d\r\n", sizeof(a));; // 4 字节而不是100 字节
    }

5.分别写出BOOL, int, float,指针类型 的变量a 与“零”的比较语句。

答:

BOOL :      if( !a ) or if( a )
int :       if(a == 0)
float :     const float EXP = 0.000001; 
            if((a >= -EXP) && (a <= EXP))
pointer :   if(a != NULL) or if(a == NULL)

6.void类型指针

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

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

例如:

    int *pint;
    void *pvoid; //它没有类型,或者说这个类型不能判断出指向对象的长度
    pvoid = pint; //只获得变量/对象地址而不获得大小,但是不能 pint = pvoid;

如果要将pvoid赋给其他类型指针,则需要强制类型转换。如:

    pint = (int *)pvoid; //转换类型也就是获得指向变量/对象大小

void指针不能复引用(即取内容的意思)
因为void指针只知道指向变量/对象的起始地址,而不知道指向变量/对象的大小(占几个字节)所以无法正确取内容。在实际的程序设计中,为迎合ANSI标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:

    void*pvoid;
    (char*)pvoid++; //ANSI:正确;GNU:正确
    (char*)pvoid+=1; //ANSI:错误;GNU:正确

7.“引用”与指针的区别是什么?

答:

  1. 引用必须被初始化,指针不必。
  2. 引用初始化以后不能被改变,指针可以改变所指的对象。
  3. 不存在指向空值的引用,但是存在指向空值的指针。
    指针是地址,指针变量是存放地址的变量,是对目标变量的间接操作。
    引用实质就是目标变量的别名,对引用的操作就是对目标变量的操作。

8、下面这段代码的输出结果为:A

#include
void change(int * a, int &b, int c)
{
    c = *a;
    b = 30; //引用
    *a = 20;
}

int main ( )
{
    int a=10, b=20, c=30;
    change(&a,b,c);
    printf(“%d,%d,%d,”,a,b,c);
    return 0;
}

A 20, 30, 30
B 10, 20, 30
C 20, 30, 10
D 10, 30, 30

static

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

答:
1)在函数内,修饰变量为静态局部变量,仅初始化一次,函数调用中维持其上次值。
2)在文件内,修饰变量为本地静态全局部变量,仅初始化一次,仅本文件内使用,其他文件不可用。
3)在文件内,修饰函数为本地静态函数,仅本文件内使用,其他文件不可用。

2.static局部变量 和 普通局部变量 有什么区别?

答:
1)static局部变量 与 普通局部变量 的作用域相同,都是函数内,但存储类型不同。
2)static局部变量 是 静态存储方式,生存期是一直存在;
3)普通 局部变量 是 非静态存储方式, 生存期是本次函数调用,函数返回则释放。

3.static全局变量 与 普通全局变量 有什么区别?

答:
1)static全局变量 与 普通全局变量 都是 静态存储方式,但作用域不同。
2)static全局变量作用域 限一个源文件内使用;
3)普通 全局变量作用域 可多个源文件内使用。

4.static函数 与 普通函数 有什么区别?

答:static函数 与 普通函数 作用域不同。static函数仅本文件内使用。普通函数 可多个文件内使用。

总结:
static对 局部变量 改变生存期;
static对 全局变量 改变作用域;
static对 函数        改变作用域;

const

1.关键字const是什么含意?

const的意思是只读,不可改变的。
作用:定义常量、修饰函数参数、修饰函数返回值三个作用。
定义:const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的。
目的:const 推出的初始目的是为了取代预编译指令,消除它的缺点,同时继承它的优点。

2.下面const声明都是什么意思?

const int a; //a是一个 常整型数
int const a; //a是一个 常整型数
const int *a; //a是一个指向 常整型数 的指针(整型数是不可修改,但指针可以)
int * const a; //a是一个指向整型数的 常指针(指针指向的整型数是可以修改的,但指针是不可修改的
const int * const a; //a是一个指向 常整型数的 常指针(指针指向的整型数 和 指针 都不可修改)

3.请说出 const 与 #define 相比,有何优点?

答:被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。

4.使用 const 理由

(1)定义const常量,具有不可变性。
         例如:const int Max=100; int Array[Max];
(2)可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改。
         如(1)中,如果想修改Max的内容,只需要:const int Max=you want;即可!
(3)便于进行类型检查,使编译器对处理内容有更多了解,消除了一些隐患。
         例如:void f(const int i) { .........} 编译器就会知道i是一个常量,不允许修改;
(4)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。
         如(2),如果在函数体内修改了i,编译器就会报错;
(5)可以节省空间,避免不必要的内存分配。
         例如:

    #define PI      3.14159 //常量宏
    const double PI = 3.14159; //此时并未将Pi放入RAM中 ......
    double a=PI; //此时为Pi分配内存,以后不再分配!
    double b=PI; //编译期间进行宏替换,分配内存
    double c=Pi; //没有内存分配
    double d=PI; //再进行宏替换,又一次分配内存!
const 定义常量从汇编的角度来看,只是给出了对应的内存地址;
#define 给出的是立即数;
所以,const 定义的常量在程序运行过程中只有一份拷贝,
而 #define 定义的常量在内存中有若干个拷贝。

(6)提高了效率。
编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

volatile

1.关键字volatile有什么含意 并给出三个不同的例子。

答:volatile是易改变的意思,定义volatile的变量编译器就不会去优化它了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:
1)并行设备的硬件寄存器(如:状态寄存器)
2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3)多线程应用中被几个任务共享的变量
volatile关键字是一种类型修饰符。
作用:防止编译器对代码进行优化。
使用地方:
1)中断服务程序中修改的供其它程序检测的变量需要加volatile;
2)多任务环境下各任务间共享的标志应该加volatile;
3)存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;
       另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现, 2 中可以禁止任务调度,3中则只能依靠硬件的良好设计了。

2.一个参数既可以是const还可以是volatile吗?解释为什么。

答:是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

3.一个指针可以是volatile 吗?解释为什么。

答:是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

4.下面的函数有什么错误:

int square(volatile int *ptr)
{
    return *ptr * *ptr;
}

答:这段代码的有个恶作剧。这段代码的目的是用来返指针ptr指向值的平方,但是,由于ptr指向一个volatile型参数,编译器将产生类似下面的代码:

int square(volatile int *ptr)
{
    int a,b;
    a = *ptr;
    b = *ptr;
    return a * b;
}

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!
正确的代码如下:

long square(volatile int *ptr)
{
    int a;
    a = *ptr;
    return a * a;
}

5.const, volatile含义

(1)const含义是“请做为常量使用”,而并非“放心吧,那肯定是个常量”。
(2)volatile的含义是“请不要做自以为是的优化,这个值可能变掉的”,而并非“你可以修改这个值”。

6.const, volatile的作用以及起作用的阶段

(1)const只在编译期有用,在运行期无用
const在编译期保证在C的“源代码”里面,没有对其修饰的变量进行修改的地方(如有则报错,编译不通过),而运行期该变量的值是否被改变则不受const的限制。
(2)volatile在编译期和运行期都有用
在编译期告诉编译器:请不要做自以为是的优化,这个变量的值可能会变掉;
在运行期:每次用到该变量的值,都从内存中取该变量的值。

补充:

编译期 -- C编译器将源代码转化为汇编,再转化为机器码的过程;

运行期 -- 机器码在CPU中执行的过程。

7.const, volatile同时修饰一个变量

答:
(1)“编译器一般不为const变量分配内存,而是将它保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作。”
(2)volatile的作用是“告诉编译器,随时可能发生变化的,每次使用它的时候必须从内存中重新取出”。

运算

1.下面的代码输出是什么,为什么?

void foo(void)
{
    unsigned int a = 6;
    int b = -20;
    (a+b > 6)? printf("> 6") : printf("<= 6");
}

答案:“>6”。
原因:当表达式中存在 有符号类型无符号类型 时,所有的操作数都自动转换无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。

2.C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?**

int a = 5, b = 7, c;
c = a+++b;

答案:合法,但规范不好。这段代码持行后a = 6, b = 7, c = 12。

3.请写出下列代码的输出内容

#include
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

4.写出下列代码的输出内容

#include
int inc(int a)
{
    return(++a);
}
    
int multi(int *a, int *b, int *c)
{
    return(*c = *a * *b);
}

typedef int(FUNC1)(int in);
typedef int(FUNC2) (int*,int*,int*);
void show(FUNC2 fun,int arg1, int*arg2)
{
    FUNC1 p = &inc;
    int temp = p(arg1);
    fun(&temp, &arg1, arg2);
    printf(“%d\n”, *arg2);
}

main()
{
    int a;
    show(multi, 10, &a);
    return 0;
}

答:110

5.请找出下面代码中的所以错误

说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”

#include”string.h”
main()
{
    char* src = ”hello,world”;
    int len = strlen(src);
    char* dest = (char*)malloc(len);
    char* d = dest;
    char* s = src[len];
    while(len–- != 0) d++ = s–-;
    printf(“%s”,dest);
    return 0;
}

答:方法1:

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;
}

方法2:

#include<string.h>
#include<stdio.h>

int main(void)
{
    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;
}

6.请问下面程序有什么错误?

int a[60][250][1000], i, j, k;
for(k=0; k<=1000; k++)
for(j=0; j<250; j++)
for(i=0; i<60; i++)
a[i][j][k]=0;

答案:把循环语句内外换一下

7.请问下面程序会出现什么情况?

#define Max_CB 500

void LmiQueryCSmd(Struct MSgCB * pmsg)
{
    unsigned char ucCmdNum;
    ......
    for(ucCmdNum=0; ucCmdNum<Max_CB; ucCmdNum++)
    {
        ......;
    }
}

答案:死循环

变量作用域

1.全局变量 和 局部变量 在内存中是否有区别?如果有,是什么区别?

答:
1)全局变量储存在静态数据区,局部变量在堆栈中。
2)全局变量的作用域是整个函数,局部变量的作用域是声明该变量的函数

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

答:能,局部会屏蔽全局。要用全局变量,需要使用"::"

3.全局变量 可不可以定义在可被多个.C文件包含的头文件中?为什么?

答:可以,在不同的C文件中以static形式来声明同名全局变量。只能有一个C文件中对此变量赋初值,此时连接不会出错。

4.如何引用一个已经定义过的 全局变量?

答:用extern关键字 在 头文件 中 声明全局变量。

内存

1.程序的内存分配

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

int a=0; //全局初始化区
char *p1; //全局未初始化区
main()
{
    int b; //栈
    char s[]=”abc”; //栈
    char *p2; //栈
    char *p3=”123456″; //123456\\0在常量区,p3在栈上。
    static int c=0; //全局(静态)初始化区
    p1 = (char*)malloc(10);
    p2 = (char*)malloc(20); //分配得来得10和20字节的区域就在堆区。
    strcpy(p1,”123456″); //123456\\0放在常量区,编译器可能会将它与p3所向”123456″优化成一个地方。
}

2.访问固定的内存位置。绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器,写代码去完成这一任务。

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

一个较晦涩的方法是:
*(int * const)(0x67a9) = 0xaa55;

即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。

3.队列和栈有什么区别?

答:队列先进先出,栈后进先出

4.解释 堆(heap)和 栈(stack) 的区别

答:
1)申请方式。
stack:由系统自动分配。
例如:声明在函数中一个局部变量int b; 系统自动在栈中为b开辟空间

heap:需要程序员自己申请,并指明大小。在c中malloc函数
如:p1 = (char*)malloc(10); //在C++中用new运算符。注意p1本身是在栈中的。 `

2)申请效率的比较。
栈: 由系统自动分配,速度较快。但程序员是无法控制的。
堆: 是由malloc/new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
3)申请大小的限制。
栈:系统预先规定好的.事先配置好。栈获得的空间较小。
堆:程序员自己定义堆获得的空间比较灵活,也比较大。
4). 堆和栈中的存储内容。
栈:存储函数 局部临时变量、现场的保护等。
堆:堆中的具体内容由程序员安排。

5.堆栈溢出一般是由什么原因导致的?

答:
1.没有回收垃圾资源;
2.层次太深的递归调用

常见标准库函数

1.sizeof与strlen的区别

char str[20]="0123456789";
int a=strlen(str); //a=10; strlen计算字符串的长度,以'\0'为字符串结束标记(长度不包含'\0')。
int b=sizeof(str); //b=20; sizeof计算数组str[20] 所占的内存空间的大小,不受里面存储的内容影响。
char* ss = "0123456789";

sizeof(ss)结果 4 ——> ss是指向字符串常量的字符指针,sizeof 获得的是一个指针的之所占的空间。
sizeof(*ss)结果 1 ——> *ss是第一个字符 '0' 所占的内存空间,是char类型的,占了1位
strlen(ss)结果 10 ——> 如果要获得这个字符串的长度,则一定要使用 strlen
sizeof结构体为结构体中定义的数据类型的总的空间(注意字节对齐)。
sizeof对union为union中定义的数据类型的最大数据类型的大小。

2.以下代码中的两个sizeof用法有问题吗?

void UpperCase( char str[] ) //将 str 中的小写字母转换成大写字母
{
    for(int i=0; i<sizeof(str); i++)
    {
        if( 'a'<=str[i] && str[i]<='z' )
        str[i] -= ('a'-'A' );
    }
}

char str[] = "aBcDe";
printf("str字符长度为:" sizeof(str) / sizeof(str[0]));
UpperCase( str );
printf("%s", str );

答:

1)、函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。

2)、函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。

3、有一个如下的结构体:

struct A
{
    long a1;
    short a2;
    int a3;
    int *a4;
};

请问在64位编译器下用sizeof(struct A)计算出的大小是多少? A
A 24
B 28
C 16
D 18

常见算法

1、冒泡排序算法的时间复杂度是什么?

答 :O(n^2)

/**
  ******************************************************************************
  * @brief   冒泡排序加强版 函数
  * @param   *ary    数据指针
  * @param   len     数据长度
  * @param   dir     排序方向(1--降序;0--升序) 
  * @return  None
  * @note    升降排列通用 
  ******************************************************************************
  */
#define BubbleType     int //元素类型
void BubbleSortPlus(BubbleType *ary, unsigned char len, unsigned char dir)
{
	BubbleType tmp;
	unsigned char i, j;

	len--; //自减1。注意不能少 
	for(i=0; i<len; i++) //外循环为排序趟数,len个数进行len-1趟
	{
		for(j=0; j<len-i; j++) //内循环为每趟比较的次数,第i趟比较len-i次
		{
			if((ary[j] < ary[j+1]) ^ dir) //相邻元素比较,若逆序则交换(升序为左大于右,降序反之)
			{
				tmp = ary[j];
				ary[j] = ary[j+1];
				ary[j+1] = tmp;
			}
		}
	}
}

2、对一个含有20个元素的有序数组做二分查找,数组起始下标为1,则查找A[2]的比较序列的下标为(B)

A 9,5,4,2
B 10,5,3,2
C 9,6,2
D 20,10,5,3,2

int BinSearch(const int *Array, int low, int high, int target)
{
    int mid;
    while(low <= high)
    {
        mid = low + (high - low) / 2;
        if(target == Array[mid])  return mid;
        else if(target < Array[mid]) high = mid - 1;
        else if(target > Array[mid]) low  = mid + 1;      
    }
    return -1;
}

3、线性表(a1,a2,…,an)以链接方式存储时,访问第i位置元素的时间复杂性为(C)

A O(i)
B O(1)
C O(n)
D O(i-1)

4、在一个10阶的B-树上,每个树根结点中所含的关键字数目最多允许为( )个,最少允许为( )个。B

A 10,5
B 9,4
C 8,3
D 7,6

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式工程师 面试题 集-C语言 的相关文章

  • numpy 多级排序 :lexsort 函数详解

    目录 1 lexsort 排的是个啥 2 举个例子 1 lexsort 排的是个啥 lexsort 函数的定义如下 xff1a def lexsort keys axis 61 None lexsort是一种多级排序方法 作用为对给定的 k
  • 5.1 Spark的安装与使用

    第一关 Scala语言开发环境的部署 1 下载解压 在Scala官网根据平台选择下载Scala的安装包scala 2 17 7 tgz 解压到 app目录下 xff1a mkdir app 创建 app 目录 cd opt tar zxvf
  • 5.7 Spark简单算子案例(Python版)

    第一关 WordCount 词频统计 编程要求 对文本文件内的每个单词都统计出其出现的次数 按照每个单词出现次数的数量 xff0c 降序排序 文本文件内容如下 xff08 单词与单词之间以空格进行分割 xff09 xff1a hello j
  • day01 开始

    一 介绍 夏培肃 造计算机第一代 李国杰 黄令仪 胡伟武 刘阳 底层 应用层 APP 金庸 xff1a 内练一口气 外练筋骨皮 内功 外功 操作系统 BIOS 3w 操作系统原理 计算机原理 STM32 100 30 70 上午 xff1a
  • day02 LED

    一 回顾 1 C int char short typedef 起别名 指针 函数 void fun T int x int y 结构体 2 嵌入式 以应用为中心 物联网的框架 xff1a 感知层 网络层 平台层 应用层 3 搭建开发环境
  • day03 timer

    一 回忆 计算机体系结构 总线的概念 数据总线 地址总线 控制总线 如 xff1a 0x12345678上放0x100 AHB AHB1 AHB2 APB1 APB2 编译原理 hello c 预处理 xff08 预处理器 xff09 he
  • ubuntu安装CMake

    CMake是什么呢 xff1f 根据百度百科的解释 xff0c CMake是一个跨平台的安装 xff08 编译 xff09 工具 xff0c 可以用简单的语句来描述所有平台的安装 编译过程 xff0c 能够输出各种各样的makefile或者
  • Ubuntu安装ifconfig工具

    安装命令 xff1a sudo apt install net tools
  • 通关必读—linux面试题(带答案)

    答案linux考试题 1 在登录Linux时 xff0c 一个具有唯一进程ID号的shell将被调用 xff0c 这个ID是什么 b A NID B PID C UID C CID 答 xff1a w命令查看用户tty终端信息 ps ef
  • shell判断整数变量的奇偶性

    为了简化问题和突出重点 xff0c 这里我们假设脚本的输入参数一定为合法的整数类型 xff0c 因而在脚本内部将不再进行参数的合法性判断 span class token punctuation span root 64 xieqichao
  • 《云计算全栈》-python篇:编写石头剪刀布小游戏、附带升级脚本-循环版石头剪刀布小游戏

    3 案例3 xff1a 编写石头剪刀布小游戏 3 1 问题 编写game py脚本 xff0c 实现以下目标 xff1a 计算机随机出拳 玩家自己决定如何出拳 代码尽量简化 123 3 2 方案 引用random模块生成0 2的随机数 xf
  • pytorch 层标准化 LayerNorm 的用法

    目录 1 为什么要标准化 xff08 理解的直接跳过到这部分 xff09 2 LayerNorm 解释 3 举例 只对最后 1 个维度进行标准化 4 举例 对最后 D 个维度进行标准化 1 为什么要标准化 xff08 理解的直接跳过到这部分
  • Python全套语法

    目录 学Python你应该get到的三句话 xff01 跟紧潮流不是随波逐流 xff01 投靠大佬不是投机取巧 xff01 赚取利益不是急功近利 xff01 Python全套语法重磅来袭 xff01 初识python之概念认知篇 初识pyt
  • 初识python之元组列表篇

    我们知道python的数据类型有 字符串 xff0c 数字 xff0c 列表 xff0c 元组 xff0c 字典 xff0c 函数等 xff0c 这些都是我们在进行实际开发中 xff0c 必备的一些基础性语法 xff0c 本期文章 xff0
  • Python如何把字典写入到CSV文件

    在实际数据分析过程中 xff0c 我们分析用Python来处理数据 xff08 海量的数据 xff09 xff0c 我们都是把这个数据转换为Python的对象的 xff0c 比如最为常见的字典 比如现在有几十万份数据 xff08 当然一般这
  • C 判断

    C 判断 判断结构要求程序员指定一个或多个要评估或测试的条件 xff0c 以及条件为真时要执行的语句 xff08 必需的 xff09 和条件为假时要执行的语句 xff08 可选的 xff09 C 语言把任何非零和非空的值假定为 true x
  • C 数组

    lt div class 61 34 article intro 34 id 61 34 content 34 gt C 数组 C 语言支持数组数据结构 xff0c 它可以存储一个固定大小的相同类型元素的顺序集合 数组是用来存储一系列数据
  • 为什么访问亚马逊的网站卡顿?

    lt h4 class 61 34 sectiontitle 34 gt 为什么访问亚马逊的网站卡顿 xff1f lt h4 gt 购买了 华北 北京四 的服务器 xff0c 在亚马逊开办了跨境电商网站 xff0c 使用过一段时间后 xff
  • 一文了解公有云、私有云、混合云、边缘云、专有云、分布式云

    1 公有云 公有云是为大众建的 xff0c 所有入驻用户都称租户 xff0c 不仅同时有很多租户 xff0c 而且一个租户离开 xff0c 其资源可以马上释放给下一个租户 xff0c 一如饭店里一桌顾客走了马上迎来下一桌顾客 公有云是最彻底
  • 区块链基本概念

    传统商业网络 在当前传统商业网络中 xff0c 作为整个商业网络的参与方 xff0c 各商业机构及政府 金融机构等各方独立 系统不通 xff0c 各自维护自己的数据 当发生交易时 xff0c 交易双方修改各自账本并本地维护 xff0c 形成

随机推荐

  • ChatGPT——OpenAI推出的人工智能聊天机器人

    ChatGPT OpenAI推出的人工智能聊天机器人 目录 隐藏 1 什么是ChatGPT 2 ChatGPT的应用领域 3 3 ChatGPT的原理 4 ChatGPT的发展历程 5 ChatGPT爆火的原因 6 ChatGPT带来的变革
  • HBase

    架构设计 核心概念 xff1a Client xff1a 发起读写请求的角色 xff0c 面向hbase client 编程 首先hbase查询Meta表 xff0c 找到读或写的数据的region区域位置信息 然后向region对应的HR
  • python 数组的排列与组合:combinations 与 permutations

    combinations 与 permutations 函数在python 的 itertools 库中 xff0c 因此在使用前需要 import itertools combinations 函数的作用就是罗列出所有数组中 n 个元素的
  • 在STM32下完成一个基于FreeRTOS的多任务程序

    在STM32下完成一个基于FreeRTOS的多任务程序 一 FreeRTOS简述二 MDK下移植FreeRTOS三 总结 一 FreeRTOS简述 FreeRTOS是一个热门的嵌入式设备用即时操作系统核心 已被经成功移植到35种不同的微控制
  • 【K8S】Kubernetes集群搭建流程详解

    文章目录 一 购买云服务器二 搭建Docker环境三 根据K8S官网搭建 基础环境 四 安装K8S三剑客 xff1a kubelet kubeadm kubectl五 安装K8S节点需要使用的镜像六 使用kubeadm初始化Master节点
  • springBoot maven打包[分层打包]

    打jar包 xff0c 很大 xff0c 发服务器也慢 get到一种打包方式 直接挨着cv直接就能用 一 src目录下创建assembly文件夹下assembly xml lt assembly xmlns 61 34 http maven
  • 链表-倒序排列鏈表

    剑指 Offer 06 从尾到头打印链表 38 输入一个链表的头节点 xff0c 从尾到头反过来返回每个节点的值 xff08 用数组返回 xff09 示例 1 xff1a 输入 xff1a head 61 1 3 2 输出 xff1a 2
  • 使用远程桌面链接CentOS 7

    需求 xff1a Gnome桌面环境 Xrdp Xrdp是Microsoft远程桌面协议 RDP 的开源实现 xff0c 它允许您以图形方式控制远程系统 Gnome安装 yum groupinstall 34 GNOME Desktop 3
  • vscode的下载速度会特别慢问题处理

    1 xff0c 下载太慢大部分是因为VSCODE官网服务器跟我们国内的链接速度有关 xff0c 当我们去官网下载会出现下面的情况 2 xff0c 复制下载的链接 xff0c 并且修改红框中的内容为 span style background
  • Dockerfile

    Dockerfile Dockerfile基本结构指令FROMMAINTAINERRUNCMDEXPOSEENVADDCOPYENTRYPOINTVOLUMEUSERWORKDIRONBUILD 创建镜像 Dockerfile 基本结构 D
  • 使用git时本地代码被覆盖怎么办

    1 遇事不要慌 xff0c 看本地历史记录 右键要想要恢复的代码或文件夹 61 右键 61 Local History 61 gt Show History 2 我一下就找到了本地历史记录 看右边有了不同时间的代码 xff0c 去点一下试试
  • Ubuntu截图工具flameshot的安装与快捷键设置

    https blog csdn net sexyluna article details 105884224
  • moveit配置过后gazebo加载不出来机械臂模型的问题

    我使用moveit setup assistant对dubot magician机械臂的urdf进行配置 xff0c 配置完成后发现运行gazebo launch可以打开gazebo xff0c 但是却什么也没有 xff0c 机械臂模型加载
  • 上传本地项目代码到GitHub的方法

    预备知识 xff1a 有一个GitHub账号 xff0c 然后知道怎么进GitHub网页 之前往GitHub上传代码都是现场百度找指令操作的 xff0c 从来不记 xff0c 这次干脆做个记录当个笔记吧 Git是一个版本控制软件 xff0c
  • 单片机之蜂鸣器

    蜂鸣器简介 无源蜂鸣器 xff1a 有绿色电路板的一种 有源蜂鸣器 xff1a 没有电路板用黑胶封闭的一种 其实蜂鸣器的种类有很多 例如 xff1a 电磁式蜂鸣器 xff1a 由振荡器 电磁线圈 磁铁 振动膜片及外壳组成 同时电磁式蜂鸣器也
  • Centos Stream 9 安装 Docker 23.0.2 社区版 官方安装教程

    目录 一 内核的版本必须大于3 10使用下面的命令来检查是否满足docker的要求 xff0c 进行依赖性检查 二 安装docker容器引擎 xff0c 需要一个具有sudo权限的账户登录进行操作 1 更新现有yum包 2 遇到提示请输入y
  • AttributeError: module numpy has no attribute int .报错解决方案

    在训练YOLO模型时突然发现这个报错 xff0c 后来发现是numpy版本问题 xff0c yolo官方给的是大于等于1 18 5 xff0c 当你执行pip install r requirements txt命令时 xff0c 他默认安
  • 单片机(嵌入式)程序分层架构

    目录 前言 嵌入式3层软件架构 嵌入式4层软件架构 1 驱动层 操作系统层 中间件层 应用层 嵌入式4层软件架构 2 硬件层 嵌入式微处理芯片 嵌入式存储器系统 嵌入式I O接口 中间层 系统软件层 RTOS 文件系统 GUI 应用层 嵌入
  • FreeRTOS笔记—第一章 FreeRTOS概述

    1 1 认识FreeRTOS 1 1 1 什么是操作系统 操作系统 xff08 Operating System xff0c 简称OS xff09 是管理计算机硬件与软件资源的计算机程序 简单说就是一种管理计算机资源的软件 目的是为了高效
  • 嵌入式工程师 面试题 集-C语言

    预编译 1 什么是预编译 xff0c 何时需要预编译 答 xff1a 预编译又称预处理 就是做些代码文本的替换工作 开头的指令 xff0c 比如拷贝 include 包含的文件代码 xff0c define 宏定义的替换 xff0c 条件编