IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 西邮Linux兴趣小组2021纳新面试题简析 -> 正文阅读

[系统运维]西邮Linux兴趣小组2021纳新面试题简析

?sizeof()是一个运算符,括号内为一个变量或者一个变量类型,结果为它所占空间的大小(以字节为单位)。

strlen()是一个函数,计算括号内字符串的长度,不包括'\0'

详情见转载:

C语言中sizeof()和strlen()的区别_追梦的小蚂蚁-CSDN博客_sizeof和strlen在c语言的区别

相等,均为16.

有内存对其规则可以知道:

test1:a(4字节)从地址0开始占用0、1、2、3四个单元,b(2字节)占用4、5单元,c(8字节)内存对齐占用8、9、10、11、12、13、14、15单元,最后内存对齐补齐到16

test2:b同理占用0-1,a占用4-7,c占用8-15单元,补齐16

详情见转载:

C/C++内存对齐详解 - 知乎

?

?

void(int a[],int n:)
{
    for(int i = 0;i < n;i++)
    {
        for(int j = 0;j < n;j++)
        {
             printf("%d",a[i][j]);   
        }
    }
}

?传值:把A的数值传到B,改变B,A不会跟着变,B存的是跟A一样的值,只是在子函数里做了一个拷贝,把传入的值赋给了子函数的形参。子函数无法修改A的值。

传址:把A的地址作为实参传给子函数的形参B,B的值为A的地址,通过地址访问A,便可以改变A的值。

变量的生命周期:

  • 变量的生命周期就是从创建该变量开始到该变量被销毁的这一段时间,
    各种变量的生命周期:
  • 全局变量:进程开始时创建,进程结束时销毁,在代码编译链接后,直接将
    其初始值写入到可执行文件中,创建时按照定义时的初始值进
    行赋值
  • 局部变量和参数变量:进入函数时创建,退出函数时销毁
  • 全局静态变量:定义一个全局变量并使用static关键字修饰时,这个变量
    就成了全局静态变量,它的生命周期和全局变量一样,但是
    作用域被限制在定义文件内,无法使用extern来让其他源
    文件中使用它
  • 静态局部变量:在函数内使用static关键字修饰一个变量时,这个变量就
    是静态局部变量,它的生命周期同全局变量一样,作用域被
    限制在函数内
  • 寄存器变量:在VC++的Debug版本中,寄存器变量和普通变量没区别,在
    Release版本中VC++编译器会自动优化,即使一个变量不是
    寄存器变量也有可能放到寄存器中,所以register关键字对
    于VC++编译器来说只是个建议。

#include<stdio.h>
int ver=123;
void func1(int ver)
{
    ver++;变为1026
    printf("ver=%d\n",ver);//第三行输出ver=1026
}
 
void func2(int*pr)//传入ver的地址给指针pr
{
    *pr=1234;//在此函数内部修改pr指向的ver中的值为1234
    printf("*pr=%d\n",*pr);//第五行输出
    pr=5678;//警告(直接把int型常量赋值给int*指针)pr指向了别处。
    printf("ver=%d\n",ver);
//第六行输出,该函数内并没有ver这个变量,没有覆盖全局变量的值,因此输出为全局变量的值
}
 
int main()
{
    int a=0;//函数内部变量
    int ver=1025;//函数内的ver覆盖了全局变量ver的值变为1025
    for(int a=3;a<4;a++)
    {
        static int a=5;//静态局部变量(作用域为这个循环,且每次进入循环时的值都为5)
        printf("a=%d\n",a);//第一行输出a=5
        a=ver;//a=1025
        printf("a=%d\n",a);//第二行输出a=025
        func1(ver);//将1025赋给函数形参ver
        int ver=7;//
        printf("ver=%d\n",ver);//第四行输出
        func2(&ver);//将ver的地址传给函数形参pr
    }
    printf("a=%d\tver=%d\n",a,ver);//0 1025(函数内部变量会覆盖全局变量)
    return 0;
}

上面程序的输出结果为:

a=5
a=1025
ver=1026
ver=7
*pr=1234
ver=123
a=0?? ?ver=1025

?

?

 

利用递归当n不为0时不停返回sum(n-1)调用自己从而完成从1~100的累加,因为n为unsigned无符号整形,所以减到0后sum(n-1=0)+n=sum(0)+1=1,所以sum(0)=0,再逐层返回0+1+2+...+100=5050。

?

#include<stdio.h>
void func(void);
int main()
{
    func();
    return 0;
}
void func(void)
{
    short a=-2;
    unsigned int b=1;
    b+=a;
    int c=-1;
    unsigned short d=c*256;
    c<<=4;
    int e=2;
    e=~e|6;
    d=(d&0xff)+0x2022;
    printf("a=0x%hx\t b=0x%x\t d=0x%hx\t e=0x%x\n",a,b,d,e);/
    printf("c=0x%hhx\t\n",(signed char) c);//(hhx = short short x)
}

?输出结果为:

a=0xfffe? b=0xffffffff???? d=0x2022???? e=0xffffffff

c=0xf0

这是关于函数运算符的考察:

?转载博客:C语言位运算符基础_kevinchan1207的博客-CSDN博客

?

关于指针和数组可以看这篇博客:如何看待一维数组以及二维数组的数组名、首元素、数组地址_季末狂甩的博客-CSDN博客_一维数组的数组名

#include<stdio.h>
int main()
{
    int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};
    int (*b)[3]=a;
    /*a做右值时相当于二维数组首元素的首地址,即&a[0][0],但它的类型是
      一个指向一个内含三个int类型值的数组的指针,即指向a[0]*/
    /*而int (*b)[3]也是一个指向内含三个int类型值的数组,等号两边两个指针类型相同,
      将右边指针的值赋给左边指针.即b也指向了a[0]*/

    ++b;//因上述理由,此时b指向了a[1]

    b[1][1]=10;
    /*此时b是指向a[1]的,所以b[1](即*(b+1))为a[2],b[1][1]即a[2][1],
      所以该语句执行的操作为:将10放在a[2][1]的值由7改为10*/
    int*ptr=(int*)(&a+1);
     /*&a表示的是整个二维数组的地址,+1加了整个二维数组的地址,&a+1为a后边一个
       3*3*4=36个字节的空间的地址,强制类型转换为一个指向int类型的指针,即指向
       a后边一个4字节的空间(一个int)*/
     /*所以此时ptr为一个指向a后边一个4字节的空间(一个int)的指针。*/
    printf("%d %d %d\n",a[2][1],**(a+1),*(ptr-1));
    */a[2][1]的值为10。(a+1)指向第二个一维数组,两次解引用得到第二个一维数组的
      第一个元素4。ptr-1指向第三个一维数组的最后一个元素,解引用一次得到9*/
    return 0;
}

结果为10 4 9.

仅考虑语法的情况下:

  • func0:传值语法均正确。

  • func1:传址语法均正确。

  • func2:*n += 1语法错误,const int *n为通过指针不可修改变量。

  • func3:n = &a语法错误,int *const n为指针指向不可修改。

  • func4:*n += 1和n = &a语法均错误,const int *const n为通过指针不可修改变量,同时指针指向也不可修改。

  • const int 和int const没有区别都是指此int类型的变量不能被修改。

  • 同理const int*和int const*也没有区别,都是指指针指向的值不能被改变。

#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define N 44
char *convert(const char *s);
int main()
{
    char *str="XiyouLinux Group 2022";
    char *temp=convert(str);
    puts(temp);
    return 0;
}
char *convert(const char *s)
{
    int len=strlen(s);
    char *k=(char*)malloc(N);//在函数中分配一段空间并且让指针k指向这段字符串的位置
    char *t=s;//指针t用来保存原字符串s的位置
    memset(k,0,N);//将新分配的内存空间中的数全部置为0
    char str[N];//用一个数组来存放转换后的字符串
    for(int i=0;*s!='\0';*s++,i++)
    {
        if(*s>='a'&&*s<='z')
            str[i]=toupper(*s);
        else if(*s>='A'&&*s<='Z')
            str[i]=tolower(*s);
        else 
            str[i]=*s;
    }
    strcpy(k,str);//将转换后的字符串存放进申请的新内存空间
    t=k;//使存放原s字符串的位置的指针改指向新的位置(新分配的内存空间)
    return t;
}

?

?

swap1和swap2均正确,用宏定义函数进行文本替换。

关于宏替换里用do{...}while(0),可参考以下博文:

do{...}while(0)的用法_majianfei1023的专栏-CSDN博客_do while怎么用

swap3错误,只传递了a,b的值,没有传递地址,仅仅在函数内交换了a,b的值,并没有作用到外面,应该传递地址。

关于argc和argv的含义,查阅资料如下:?

?argc和argv参数在用命令行编译程序时有用。main( int argc, char* argv[], char **env ) 中?
????????第一个参数,int型的argc,为整型,用来统计程序运行时发送给main函数的命令行参数的个数,在VS中默认值为1。?
????????第二个参数,char*型的argv[],为字符串数组,用来存放指向的字符串参数的指针数组,每一个元素指向一个参数。各成员含义如下:?
????????argv[0]指向程序运行的全路径名?
????????argv[1]指向在DOS命令行中执行程序名后的第一个字符串?
????????argv[2]指向执行程序名后的第二个字符串?
????????argv[3]指向执行程序名后的第三个字符串?
????????argv[argc]为NULL?
????????第三个参数,char**型的env,为字符串数组。env[]的每一个元素都包含ENVVAR=value形式的字符串,其中ENVVAR为环境变量,value为其对应的值。平时使用到的比较少。?

遍历方法如下:

#include<stdio.h>
int main(int argc,char*argv[])
{
    int i = 0;
    while(argv[i] != NULL)
        printf(%s\n",argv[i++]);
    return 0;
}

?

?func1和func2正确,func3错误。

区别如下:

static全局变量与普通的全局变量
static全局变量只初使化一次,作用域被限制在该变量的源文件内有效,防止在其他文件单元中被引用

static局部变量和普通局部变量
static局部变量只被初始化一次,下一次依据上一次结果值,函数结束后,static局部变量所占不会被释放,生命周期不会结束,只是出函数之后出了它的作用域。

static函数与普通函数
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

详情见此博文:

static--静态变量与普通变量的区别_yang_B621的博客-CSDN博客_静态变量

?此题有关字节序大小端法,详情如下

字节序:大端法和小端法 - Broglie - 博客园

?大概就是这样一个过程:

?

先将源文件翻译为计算机可以识别的机器指令,然后再让及算计执行这些指令。
翻译的过程主要使编译+链接;

编译器编译各个源文件为目标文件,然后由链接器链接各个目标文件成为可执行文件;

?详情请见:谈谈C语言从源文件变为可执行文件之间发生的过程详解(C程序的编译链接运行)_呋喃吖的博客-CSDN博客_c文件编译可执行文件

一个由c/C++编译的程序占用的内存分为以下几个部分:
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

1.1 栈简介

栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,其操作方式类似于数据结构中的栈。参考如下代码:

int main() {
	int b;				//栈
	char s[] = "abc"; 	//栈
	char *p2;			//栈
}

?

其中函数中定义的局部变量按照先后定义的顺序依次压入栈中,也就是说相邻变量的地址之间不会存在其它变量。栈的内存地址生长方向与堆相反,由高到底,所以后定义的变量地址低于先定义的变量,比如上面代码中变量 s 的地址小于变量 b 的地址,p2 地址小于 s 的地址。栈中存储的数据的生命周期随着函数的执行完成而结束。
1.2 堆简介

堆由开发人员分配和释放, 若开发人员不释放,程序结束时由 OS 回收,分配方式类似于链表。参考如下代码:

int main() {
	// C 中用 malloc() 函数申请
	char* p1 = (char *)malloc(10);
	cout<<(int*)p1<<endl;		//输出:00000000003BA0C0
	
	// 用 free() 函数释放
	free(p1);
   
	// C++ 中用 new 运算符申请
	char* p2 = new char[10];
	cout << (int*)p2 << endl;		//输出:00000000003BA0C0
	
	// 用 delete 运算符释放
	delete[] p2;
}

?

其中 p1 所指的 10 字节的内存空间与 p2 所指的 10 字节内存空间都是存在于堆。堆的内存地址生长方向与栈相反,由低到高,但需要注意的是,后申请的内存空间并不一定在先申请的内存空间的后面,即 p2 指向的地址并不一定大于 p1 所指向的内存地址,原因是先申请的内存空间一旦被释放,后申请的内存空间则会利用先前被释放的内存,从而导致先后分配的内存空间在地址上不存在先后关系。堆中存储的数据若未释放,则其生命周期等同于程序的生命周期。

关于堆上内存空间的分配过程,首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确地释放本内存空间。由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动地将多余的那部分重新放入空闲链表。
?

详情如下:

?关于堆栈的讲解(我见过的最经典的)_yingms的专栏-CSDN博客_堆栈

一文读懂堆与栈的区别_Dablelv的博客专栏-CSDN博客_堆和栈的区别

前提为,另一个文件中的函数,不能是静态函数,即不能有static修饰。

调用方法:在调用前进行声明,然后直接调用即可

声明方法:如调用函数为int func(int a),那么在调用前只需要加上int func(int a);这样声明后,即可使用func。

在同一个项目里面的源文件之间的函数一般情况下是可以互相调用的,前提是要声明以及不限制它的作用域

创建文件夹:

格式:mkdir [选项] DirName

mkdir命令功能:

通过 mkdir 命令可以实现在指定位置创建以 DirName(指定的文件名)命名的文件夹或目录。要创建文件夹或目录的用户必须对所创建的文件夹的父文件夹具有写权限。并且,所创建的文件夹(目录)不能与其父目录(即父文件夹)中的文件名重名,即同一个目录下不能有同名的(区分大小写)。

mkdir命令选项说明:

命令中的[选项]一般有以下两种:

-m??? 用于对新建目录设置存取权限,也可以用 chmod 命令进行设置。

-p???? 需要时创建上层文件夹(或目录),如果文件夹(或目录)已经存在,则不视为错误。

创建文件:

方法一:

格式:cat>>filename

使用cat创建文件时,以系统默认的文件属性作为新文件的属性,并接受键盘输入作为文件的内容。输入结束时按Ctrl+d退出并保存文件。

方法二:

格式:touch filename

首先,touch命令用的并不多,主要用于修改指定文件的访问和修改时间属性。当文件不存在时,则创建一个新的文件。touch只能以当前时间作为访问和修改时间属性值创建一个空文件。

ls命令每一列的含义:

?查看文件属性(访问,创建,修改时间):

命令格式:stat 文件名

第一行:ATime ——文件的最近访问时间,只要读取时间,ATime就会更新

第二行:MTime ——文件的内容最近修改的时间,当文件进行被写的时候,CTime就会更新

第三行:CTime——文件属性最近修改的时间,当文件的目录被修改,或者文件的所有者,权限等被修改时,CTime就会更新。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-12-15 18:43:00  更:2021-12-15 18:44:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 5:34:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码