C语言(二)

1、sizeof(fun)=1
sizeof(&fun)=4 fun为函数名
解释:函数名其实是一个符号表,占用一个字节,虽然函数名可以当做函数的入口地址,当做一个指针,但是并不能像指针那样占用4个字节,当取地址的时候,确定是4个字节
2、存储类型
auto:默认情况下,所有的变量都是auto
register:表示变量是存放在CPU寄存器中,而不是存放在内存里面,因此不能用&符号取内存地址
extern:声明变量或者函数是来自外部的文件
static:
修饰局部变量:作用域为定义该局部变量的函数内,存储在静态区,由于是静态的,变量的生命周期被延长,只初始化一次,函数调用结束不被销毁。
修饰全局变量:作用域从定义开始到文件结尾,其他文件即使用extern也无法访问,存储在静态区,
修饰函数:限定函数的作用域为本文件
3、const与volatile
const:被const修饰的对象意味着只读
volatile:这个关键字告诉编译器所修饰的对象可能会在编译器监控之外被改变,编译器所执行的某些例行优化行为不能应用在该对象身上,精确地说就是优化器每次用到这个变量时必须小心地读取这个变量的值,而不是使用保存在寄存器里的备份
应用volatile的例子
并行设备的硬件寄存器(如状态寄存器)
中断服务子程序中会访问的非自动变量
多线程应用中被几个任务共享的变量
4、数组
int a[100] sizeof(a)=400
柔性数组:
struct mydata
{
int a;
int data[0];
};
sizeof(struct mydata)=4,data[0]不占内存空间,具体参考C深度剖析

eg:在 32 位的 x86 系统下,输出的值为多少?
#include<stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int )a + 1);
printf(“%x,%x”,ptr1[-1], ptr2);
return 0;
}
解析:
低地址0x010x000x000x000x020x000x000x00高地址
如上图所示,数组中的1和2在内存中是这样形式存储的,要好好理解下元素之间的内存排布和元素内部四个字节之间的内存排布,大小端是针对元素内部四个字节之间的排布而言的,(int)a+1表示将a数组首元素的地址转为整数,加1表示,往后偏移1个字节,再转为(int
)表示指向从新地址开始的4个字节,如图中红色部分所示。这四个字节表示一个数据,考虑到是小端序,那么真实数据就是0x0200 0000,所以最后的打印结果是5和2000000

5、库特性
(1)什么是库
库是函数源码的二进制文件(某种特殊的二进制,不是可执行文件)
(2)库的分类
静态库
动态库(共享库)
(3)库的名称
静态库:libxxx.a 以lib开头,.a结尾
动态库:libxxx.so 以lib开头,.so结尾

例子:libabc.a 这个整体叫做静态库,而其中的abc叫做静态库名称
lib123.so 整体叫做动态库,其中123叫做动态库名称

2、库的特点
静态库:使用静态库时(编译时),库的相关二进制信息会被加载到可执行程序中
优点:在可执行程序运行过程中,如果静态库被删除,不会影响可执行程序的运行。
缺点:如果在可执行程序中,对一个函数调用多次,那么静态库会被加载多次,造成可执行程序过大,浪费内存空间

动态库:动态库不是在编译时进行加载,而是在调用具体的函数时进行加载(有点和缺点正好和静态库相反),如果可执行程序对一个函数调用多次,动态库只会加载一次。
6、标准IO和文件IO的区别
标准IO属于库函数,有缓冲区,基于文件流指针进行操作,高级IO;文件IO属于系统调用,无缓冲区,基于文件描述符进行操作,低级IO。(其实文件IO有个内核缓冲区)
7、线程和进程的关系
进程是程序的一次执行过程,线程是拥有时间片的函数,轻量级进程
线程共享的内容:

a、线程也有缺点,那就是一个线程出现问题,整个进程可能结束。
b、进程结束,线程不复存在
c、线程哪些资源共享,哪些独有
共享的资源:静态数据,工作路径,信号操作函数,线程外的栈空间共享的(进程中打开的文件描述符),线程外的堆空间是共享的
独立资源:线程ID,线程相关寄存器,线程内部的栈空间是独立的。线程内的堆是独立的
8、线程间实现同步互斥的方法
全局变量、互斥锁、条件变量、信号量
9、编写一个程序判断大小端
int isedian()
{
unsigned int a = 0x12345678;
unsigned charp = (unsigned char)&a;
if(*p==0x12)//如果是低地址存放高位字节则为大端,返回0,否则返回1
return 0;
else
return 1;
}
10、编写一个程序实现字符串翻转
#include<stdio.h>
#include<string.h>

char *fanzhuan(char *dst)
{
char *head = dst;
char *tail = dst;
while(*tail)
{
tail++;
}
tail–;
/上面代码是定位首尾指针的位置下面代码是换字符**************/
while(head<tail)
{
char temp = *tail;
*tail = *head;
*head = temp;
head++;
tail–;
}
return dst;
}
int main(int argc, const char *argv[])
{
char buf[100];
fgets(buf,10,stdin);
if(buf[strlen(buf)-1]==’\n’)
buf[strlen(buf)-1]=’\0’;
printf("%s\n",fanzhuan(buf));
return 0;
}
11、编写一个程序实现统计字符串中,大写字母,小写字母,数字出现的个数
void tongji(char *p)
{
//先定义三个整形数组,初始化所有元素为0
int Big[26] = {0};
int Small[26] = {0};
int num[26] = {0};
while(*p)
{
if((*p>=‘0’)&&(*p<=‘9’))
{
//减去字符0是为了将字符变为整形,数组索引对应了字母表中的字母索引
//数组元素的值代表了对应字符出现的次数
num[*p-‘0’]++;
}
if((*p>=‘A’)&&(*p<=‘Z’))
{
Big[*p-‘A’]++;
}
if((*p>=‘a’)&&(*p<=‘z’))
{
Small[*p-‘a’]++;
}
p++;
}
int i = 0;
for(i =0;i<26;i++)
{
//加上字符的作用是为了变为相应的字符
if(Big[i]>0)
printf("%c:%d “,i+‘A’,Big[i]);
if(Small[i]>0)
printf(”%c:%d “,i+‘a’,Small[i]);
if(num[i]>0)
printf(”%c:%d ",i+‘0’,num[i]);
}
}
12、strcat函数
char *strcat(char *dest,const char *src)
{
char *temp = dest;
while(*dest)
dest++;
while((*dest++ = *src++) != ‘\0’)
;
return temp;
}
注:使用temp的原因是为了给别的函数传参


char *strcpy(char *dst,const char *src)
{
char *temp = dst;
while((*dst++ = src++) != ‘\0’)
;
return temp;
}
strcpy能把strSrc的内容复制到strDest,为什么还要 char
类型的返回值?
为了实现嵌套表达式,int len = strlen(strcpy(dst,src));


int strcmp(const char *cs,const char *ct)
{
unsigned char c1,c2;
while(1)
{
c1 = *cs++;
c2 = *ct++;
if(c1 != c2)
return c1< c2 ? -1 : 1;
if(!c1)
break;
}
return 0;
}


size_t strlen(const char *s)
{
const char *sc;
for(sc = s; *sc != ‘\0’;++sc)
;
return sc - s;
}

13、中断子函数不许哪些事情
不允许有传参,不许有返回值,不许有睡眠,总之不许有延时的任何操作
14、内存对齐
这个问题不好说,和编译器相关,只需要记得一次读取偶数字节效率比较高,然后记得下面几个东西,足够用了:
char 2 char 2 char 4 short 4
short 2 short 2 int 4 int 4
char 4 int 4 short 4 char 4
int 4
15、对一个二元数组a[][]而言
&a+1加的是整个数组;
a+1加的是一行
a[0]+1加的是一个元素
16、有以下程序段
int i=0;
while(i=1)
i++;
while循环执行的次数( )
解析:无限次,因为while括号里是赋值语句,不是等于,这一点一定要注意,不是第一次了
17、优先级问题
int main(){
int i=1;
int j=i++;
if((i++> ++j)&&(++i==j))
i+=j;
printf(“%d\n” ,i);
return 0;
}
请问最终输出的i值为(3 )
解析:++、–运算符优先级要比关系运算符高,赋值运算符属于最低的那一列
i++ > ++j <==>
(i++)>(++j)<==>
j=j+1;if(i>j);i++;
18、小端机器下, 下面程序的运行结果是什么? ( )
unsigned int a=0x1ffffff7;
unsigned char b=a;
char c=a;
char p=(char)&a;
printf(“%x, %x, %x” ,b, c, *p);
解析:f7, fffffff7,fffffff7
bcd都会发生截断,只赋予f7,但是在以%x格式4字节打印时,无符号补0,有符号补1,所以结果是A
18、在循环队列中数组a[0,m-1]存放队列元素, 其队头和队尾指针分别为front和rear, 则
当前队列中的元素个数是( D)
A ( front-rear+1) %m B ( rear-front+1) %m
C ( front-rear+m) %m D ( rear-front+m) %m
19 快速排序的平均时间复杂度和最坏时间复杂度分别为(D)
A O( n2), O( n2) B O( n2), O( nlogn)
C O( nlogn), O( nlogn) D O( nlogn), O( n2)
解析:快速排序平均及最优都是O( nlogn)
冒泡是 O( n2)
20.fork之后,父子进程用的不是同一个空间,而是又一个4G空间
21、网络部分相关问答
( i) 写出OSI七层模型, 对应TCP/IP四层模型, 以及主要的协议。

OSI 7层(是一种理想化的模型,还没有完整的实现)

OSITCP/IPprotocol
应用层smtp,ftp
表示层
会话层应用层
传输层传输层TCP,UDP
网络层网络层IP,ICMP,IGMP
数据链路层ARP, RARP

ARP IP地址MAC地址 RARP:MAC地址转IP地址
|物理层|网络接口与物理层|—| 指的是物理信号,接口,速率之类。包括常见物理层设备中继器(放大信号,一般小于3个)、集线器(hub,复制信号共享带宽,例如一根网线分出两根,效果是一样的,但是不能同时上网)

TCP/IP协议将OSI模型分为四层:
应用层:包括应用层,表示层,会话层
传输层: 传输层
网络层: 网络层
网络接口与物理层:包括数据链路层和物理层

( ii) 简述什么是三次
握手。 ( iii) 简述tcp与udp的异同。 ( iiii) 简述文件io与标准io的异同
(iiii)linux下的阻塞模型:阻塞IO,非阻塞IO,多路复用IO(事件驱动)
22、怎么用栈实现队列的功能
画两个栈,先进栈,然后立即出栈,再进另一个栈,再出栈
23、二叉树
满树:深度为k(k>=1)时,有2^k -1个节点的二叉树
完全二叉树:只有最下面两层有度数小于2的节点,且最下面一层的叶节点集中在最左边的若干位置上
二叉树的遍历:
先序遍历:若二叉树为空,则空操作,否则先访问根节点,再访问该节点的左子树,最后访问右子树
中序遍历:若二叉树为空,则空操作,否则先访问左子树,再访问根节点,最后访问右子树
后序遍历:若二叉树为空,则空操作,否则先访问左子树,再访问右子树,最后访问根节点
24、两个变量交换数据
a = 2; b = 4;
a = a ^ b; 110
b = a ^ b; 010
a = a ^ b; 100

a = a + b; 6
b = a - b; 2
a = a - b; 4

24、一道面试题
int i = 5;
则i+++++i的值是(12)
解析:C语言对于这样的式子有种处理方法,贪心法,详见C深度剖析,记住关键字:从左到右,成符号
则上式可以变为(i++) + (++i)== 6+6
25、%和/
除法运算符“/”。二元运算符,具有左结合性。参与运算的量均为整型时,结果为整型,舍去小数。如果运算量中有一个为实型,结果为双精度实型。
求余运算符“%”,二元运算符,具有左结合性。参与运算的量均为整型。求余运算的结果等于两个数相除后的余数,注意:求余运算符左右操作数必须为整数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

foreverwlh

你的鼓励将是我创作的巨大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值