嵌入式软件复习笔记

今天是2021年9月3日,9月加油啦~

内联函数:

https://blog.youkuaiyun.com/qq_33757398/article/details/81390151

用变量a给出下面的定义 :

(1)一个整型数: int a。
(2)一个指向整型数的指针(一重指针): int *a。
(3)一个指向指针的的指针,它指向的指针是指向一个整型数的指针(二重指针): int **a。
(4)一个有10个整型数的数组 :int a[10]。
(5)一个有10个指针的数组,这10个指针是指向整型数的(指针数组): int *a[10]。
(6)一个指向有10个整型数数组的指针(数组指针):int (*a)[10]。
(7)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(函数指针):int (*a)(int)。
(8)一个有10个指针的数组,这10个指针均指向函数,该函数有一个整型参数并返回一 个整型数(函数指针数组): int (*a[10])(int)。

给了一个地址a,分别强转类型为:int变量、int指针、数组指针、指针数组、函数指针。

int变量(int) a;
int指针(int*) a;
数组指针(int (*)[])a;
指针数组(int *[])a;
函数指针(int (*)(int))a;

在32位系统中,有如下结构体,那么sizeof(fun)的数值是?

#pragma pack(1)  
struct fun  
{  
    int i;   // 4字节  
    double d;  // 8字节  
    char c;  // 1字节  
}; 

答案:sizeof(fun)得到的结果是13。

解读:因为预处理语句 ”#prama pack(1)” 将编译器的字节对齐数改为1了,根据结构体内存对齐原则,该结构体占用的字节数为13。

求输出结果

int a[2][2][3]= { {{1,2,3},{4,5,6}},{{7,8,9},{10,11,12}}};
int *ptr=(int *)(&a+1);
printf(%d %d”, *(int*)(a+1), *(ptr-1));

数组地址

查看下面代码,p[6]等于几?

int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};  
int *p = &a[1];   

答案:等于8。

解读:p是一个int类型指针,指向a[1],p[6]表示p往后移了6个单位(每个单位4个字节)并解引用,因此p[6]等于8。

由gcc编译的C语言程序占用的内存分为哪几个部分?

栈区(stack)存放函数的参数、局部变量。
堆区(heap)提供程序员动态申请的内存空间。
全局(静态)区(static)存放全局变量和静态变量,初始化不为0的全局变量和静态变量、const型常量在一块区域(.data段),未初始化的、初始化为0的全局变量和静态变量在相邻的另一块区域(.bss段)。
程序代码区存放函数体的二进制代码和字符串常量。

以下程序中,主函数能否成功申请到内存空间?

#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
void getmemory(char *p)  
{  
    p = (char *)malloc(100);  
    strcpy(p, "hello world");  
}  
int main()  
{  
    char *str = NULL;  
    getmemory(str);  
    printf("%s\n", str);  
    free(str);  
    return 0;  
}  

答案:不能。
解读:getmemory(str)没能改变str的值,因为传递给子函数的只是str的复制值NULL,main函数中的str一直都是 NULL。正确的getmemory()如下:

①传递的是二重指针,即str的指针
void getmemory(char **p)   
{  
    *p = (char *)malloc(100);  
    strcpy(*p, "hello world");  
}  
②传递的是指针别名,即str的别名,C++void getmemory(char * &p)   
{  
    p = (char *)malloc(100);  
    strcpy(p, "hello world");  
}  

在C语言中memcpy和memmove是一样的吗?

答案:
(1)memcpy()与memmove()一样都是用来拷贝src所指向内存内容前n个字节到dest所指的地址上。

(2)不同的是,当src和dest所指的内存区域重叠时,memcpy可能无法正确处理,而memmove()仍然可以正确处理,不过执行效率上略慢些。

解读:

(1)memcpy()无论什么情况下,都是从前往后拷贝内存。当源地址在前,目的地址在后,且两个区域有重叠时,会造成拷贝错误,达不到理想中的效果。

void *memcpy(void *dest, const void *src, size_t count)  
{  
    if(dest == NULL || src == NULL || count <= 0)  return NULL;  
    char *d = (char *)dest;  
    char *s = (char *)src;  
    while(count--)  
    {  
        *d++ = *s++;  
    }  
    return dest;  
}  

(2)memmove()则分两种情况:目的地址在前,源地址在后的情况下,从前往后拷贝内容。否则从后往前拷贝内容。无论什么情况都能达到理想中的效果。

void *memmove(void *dest, const void *src, size_t count)  
{  
    if(dest == NULL || src == NULL || count <= 0)  return NULL;  
    if(dest < src)  
    {  
        char *d = (char *)dest;  
        char *s = (char *)src;  
        while (count--)  
        {  
            *d++ = *s++;  
        }  
    }  
    else  
    {  
        char *d = (char *)dest + count;  
        char *s = (char *)src + count;  
        while (count--)  
        {  
            *--d = *--s;  
        }  
    }      
    return dest;  
}  

下面代码输出结果是什么?

void main()   
{   
    char *p1 = “name”;   
    char *p2;   
    p2 = (char*)malloc(20);   
    memset (p2,0, 20);   
    while(*p2++ = *p1++);   
    printf(%s\n”, p2);   
}   

答案:输出15个’0’。

解读:由于在语句“while(*p2++ = p1++); ”中,p2每次接受p1的赋值之后,都会进行一次自增操作,因此当p1指向的字符串共5个字符(包含’\0’)都赋值给p2后,p2已经指向第六个字符’0’。

指针与引用的区别?

(1)指针是变量,存储的是地址;而引用跟原变量是同一个东西,是原变量的别名。
(2)指针有const;而引用没有。
(3)指针的值可以为NULL;而引用不行。
(4)非const指针可以改变;引用只能在定义时被初始化,之后不可改变。
(5)指针可以有多级,如二重指针;而引用只能有一级。
(6)指针和引用自增(++)的意义不一样,指针自增是地址增加,引用自增是原变量增加。
(7)sizeof指针和引用得到的大小不一样,sizeof(指针)得到的是指针本身的大小,sizeof(引用)得到的是原变量的大小。

a = b * 2; a = b / 4; a = b % 8; a = b / 8 * 8 + b % 4 ; a = b * 15;效率最高的算法?

答案:

a = b * 2a = b << 1;
a = b / 4a = b >> 2;
a = b % 8a = b & 7; // 7 = (0b111)
a = b / 8 * 8 + b % 4a = ((b >> 3) << 3) + (b & 3); // 3 = 0b11
a = b * 15a = (b << 4) - b

快速排序

https://www.cnblogs.com/lanhaicode/p/10348906.html

进程的地址空间模型?

在这里插入图片描述

text segment存储代码的区域。
data segment存储初始化不为0的全局变量和静态变量、const型常量。
bss segment存储未初始化的、初始化为0的全局变量和静态变量。
heap(堆)用于动态开辟内存空间。
memory mapping space(内存映射区)mmap系统调用使用的空间,通常用于文件映射到内存或匿名映射(开辟大块空间),当malloc大于128k时(此处依赖于glibc的配置),也使用该区域。在进程创建时,会将程序用到的平台、动态链接库加载到该区域。
stack(栈)存储函数参数、局部变量。
kernel space存储内核代码。

写出下列线程、互斥锁、信号量相关代码。

定义一个线程ID变量pthread_t tid;
创建线程pthread_create(&tid,NULL,pthread_func,NULL);
等待子线程结束,并回收资源pthread_join(tid,NULL);
与当前进程分离pthread_detach(tid);
退出调用线程pthread_exit(NULL);
取消线程pthread_cancel(tid)
创建互斥锁pthread_mutex mutex=PTHREAD_MUTEX_INITIALIZER;
初始化一个互斥锁pthread_mutex_init(&mutex,NULL);
对互斥锁上锁pthread_mutex_lock(&mutex)
对互斥锁解锁pthread_mutex_unlock(&mutex);
定义一个信号量sem_t sem;
创建信号量并初始化它的值sem_init(&sem,0,1);
信号量的值减1sem_wait(&sem);
信号量的值加1sem_post(sem);

简述TCP三次握手的过程

在这里插入图片描述
(1)第一次握手:客户端创建传输控制块,然后向服务器发出连接请求报文(将标志位SYN置1,随机产生一个序列号seq=x),接着进入SYN-SENT状态。
(2)第二次握手:服务器收到请求报文后由SYN=1得到客户端请求建立连接,回复一个确认报文(将标志位SYN和ACK都置1,ack=x+1,随机产生一个序列号seq=y),接着进入SYN-RCVD状态。此时操作系统为该TCP连接分配TCP缓存和变量。
(3)第三次握手:客户端收到确认报文后,检查ack是否为x+1,ACK是否为1,是则发送确认报文(将标志位ACK置1,ack=y+1,序列号seq=x+1),此时操作系统为该TCP连接分配TCP缓存和变量。服务器收到确认报文并检查无误后则连接建立成功,两者都进入ESTABLISHED状态,完成三次握手。

简述TCP四次挥手的过程。

在这里插入图片描述
(1)第一次挥手:客户端发出连接释放报文(FIN=1,seq=u),进入FIN-WAIT-1状态。

(2)第二次挥手:服务器收到连接释放报文后发出确认报文(ACK=1,ack=u+1,seq=v),进入CLOSE-WAIT状态。这时客户端向服务器方向的连接就释放了,这个连接处于半关闭状态,服务器还可继续发送数据。

(3)中间状态:客户端收到服务器的确认报文后,进入FIN-WAIT-2状态,等待服务器发送连接释放报文,此时仍要接收数据。

(4)第三次挥手:服务器最后的数据发送完,向客户端发送连接释放报文(FIN=1,ACK=1,ack=u+1,seq=w),进入LAST-ACK状态。

(5)第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认报文(ACK=1,ack=w+1,seq=u+1),进入TIME-WAIT状态。注意此时连接还未释放,必须进过2*MSL(最长报文寿命)的时间,客户端撤销相应的TCB后,才进入CLOSED状态。服务器一旦收到确认报文,立即进入CLOSED状态。

冯·诺依曼结构和哈佛结构异同

https://zhidao.baidu.com/question/53563956.html

不能重载的运算符(5个):

1、. (成员访问运算符)
2、.* (成员指针访问运算符)
3、:: (域运算符)
4、sizeof(长度运算符)
5、?: (条件运算符)

引用与指针的区别

https://blog.youkuaiyun.com/l477918269/article/details/90233908

类型长度

在这里插入图片描述

二叉树、前序遍历、中序遍历、后序遍历

https://www.cnblogs.com/lanhaicode/p/10358736.html

编译的整个过程:预编译、编译、汇编、链接

https://www.cnblogs.com/mhq-martin/p/11898245.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值