xiyou linux 2018面试题基本知识点

数组

num[3][3]={1,2,3,4,5,6,7,8,9}
num[1][-2]==num[0][1]==2:
取某个元素时,是先通过计算这个元素的地址,再通过计算得来的地址取得该元素的。设数组a[rows][cols](即有rows行,cols列),a[i][j]的地址为 a + i*cols + j, 所以num[1][-2]的地址为 num+1乘3-2=num+0乘3+1.与num[0][1]的地址一样。值为2;
(-1)[nums][5]看成nums[-1][5]值和nums[0][2]一样
-1[nums][5]看成-(1)nums[5]即-nums[1][5]=-nums[2][2]=-9

sizeof 与strlen

strlen是一个函数,只能以字符串做参数
sizeof运算符,可以函数做参数,返回其操作数的大小,即size_t类型的值,以字节为单位,这是一个无符号整型.
sizeof 后面的内容在编译时就已经完成了

int main(int argc, char *argv[])
{
    
    
	int a[3][2] = {
    
     2, 0, 1, 8 };
	char *str = (char *)malloc(sizeof(char) * 20);
	printf("%d\n",nums[1][-2]););
	strcpy(str, "\0101\\xb2");
	printf("%zu\n", sizeof(a));
	printf("%zu %d\n", sizeof(a[1][1] =0), a[1][1]);
	printf("%zu %zu\n", sizeof(str), strlen(str));
}

输出
24
4 8
8 6

sizeof(a)=6*4=24;

sizeof 是在编译阶段已经计算出来,而赋值是在运算过程中的,所以a[1][1]=0不会执行。输出4 8;

这里字符指针变量str用malloc动态开辟出来了一片有20个字节大小的空间,sizeof()计算 str 这个指针变量的长度为8,而strlen()函数计算的则是str指向字符串的长度。

static

把局部变量改变为静态变量后是改变了它的存储方式,即改变了它的生存期。
1.普通局部变量:存储于栈中,使用完毕会立即释放
被 static 修饰的变量总是存在内存的静态区

2.自动变量会随着函数被调用和退出而存在和消失,而static类局部变量不会,它不管其所在的函数是否被调用,都将一直存在
把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围
1.全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同

2.非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。

static静态函数:使函数的作用域仅局限于本文件,即内部函数。

static int a = 2018;
static void func(void)
{
    
    
	static int b;
	printf("a = %d, b = %d\n", a++, ++b);
}
int main(int argc, char *argv[])
{
    
    
	func( );
	func( );
	func( );
}

一个程序从源代码到可执行程序的过程

一、预编译:主要处理源代码文件中的以“#”开头的预编译指令。
1.删除所有的#define,展开所有的宏定义。
2.删除所有的注释,“//”和“/**/”。

二、编译:进行一系列词法分析语法分析、语义分析及优化后,生成相应的汇编代码文件。
1.词法分析 2. 语法分析 3. 语义分析 4. 优化 5. 目标代码生成 6. 目标代码优

三、汇编:将汇编代码转变成机器可以执行的指令(机器码文件)

四、链接

const

1.const int *p :*p指向的内容无法改变
2.int const *p:*p指向的内容不可改变
3.int * const p: *p不能改变指向,值可以变
4.const int *const p:即不改变指向也不改变内容

char y[ ] = "XiyouLinuxGroup",x[ ] = "2018";
char *const p1 = y;
const char *p2 = y;
/* (1) */ p1 = x;
/* (2) */ p2 = x;
/* (3) */ *p1 = 'x';
/* (4) */ *p2 = 'x';

1,4错误
2,3正确
总结:
如果const在 * 的左侧,则const用来修饰指针所指向的变量,即指针指向位常量;
如果const位于 * 的右侧,则const就是修饰指针本身,即指针本身就是常量。
const与#define区别
1.#define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值
2…#define 宏没有类型,而 const 修饰的只读变量具有特定的类型

数组名+1与&数组+1

int main(int argc, char *argv[])
{
    
    
	int a[5];
	printf("%p\n", a);
	printf("%p\n", a+1);
	printf("%p\n", &a);
	printf("%p\n", &a+1);
}

结果(不同计算机 结果可能不同)
0x7ffdcd368b20
0x7ffdcd368b24
0x7ffdcd368b20
0x7ffdcd368b34

a即a[0]的地址。 a+1取的是a[1]的地址,即在数组首地址上加上一个int型大小空间。

&a取的也是数组首地址 。 &a+1中的&a代表整个数组, +1后就是跳过这个数组,即加上5个int大小的空间

main函数

int main(int argc, char argv[]){/…*/}

程序由主函数开始运行,由主函数结束,主函数可调用任何函数,任何函数都不可以调用主函数
argc:参数的个数。argv[]:是一个字符指针数组,每一个元素指向一个字符串。argv[0]:指向程序的路径名,argv[1…]:指向第n个参数对应的字符串

位操作

int f(unsigned int num)
{
    
    
	for (unsigned int i = 0; num; i++)
		num &= (num - 1);
	return i;
}

&运算符,两个数对应的二进制位都为1结果为1 ,否则 为 0
第一次循环num=2018&2017等价于11111100010&11111100001 结果为11111100000,即 num = 2016
第二次循环num=2016&2015等价于11111100000 & 11111011111 结果为 11111000000,即num=1984
第三次循环num=1984&1983等价于11111000000&11110111111结果为11110000000,即num=1920

大小端

在这里插入图片描述

int main(int argc, char *argv[])
{
    
    
	char n[] = {
    
     1, 0, 0, 0 };
	printf("%d\n", *(int *)n);
}

强制转换为int*类型,按大小端模式读出,如果是小端就是0000 0000 0000 0000 0000 0000 0000 0001

结构体对齐

对齐规则

1.第一个成员在与结构体变量偏移量(offset)为0的地址处。
2.其他成员变量要对齐到对齐数的整数倍的地址处。
(1)对齐数 = 对齐系数 与 该成员大小的较小值。
(2)#pragma pack(n);中的n就是对齐系数。
(3)VS中默认的值为8;linux中的默认值为4。
3.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

struct icd {
    
    
	int a;
	char b;
	double c;
};
struct cdi {
    
    
	char a;
	double b;
	int c;
};
int main(int argc, char *argv[])
{
    
    
	printf("%zu %zu\n", sizeof(struct icd), sizeof(struct cdi));
	
}

16 24

举个例子:


1.下面的结构体大小分别是多大(假设32位机器)?
struct A {
    
    
char a; //1
char b; //1
char c; //1
};
//进行整体对齐,最大类型为1<对齐系数4,按1整体对齐,所以1+1+1=3 
struct B {
    
    
int a;  //4
char b; //1
short c;//2
};
//进行整体对齐,最大类型为4=对齐系数4,所以按4整体对齐4 1+2=3<4 对齐4 所以4+4=8 
struct C {
    
    
char b; //1
int a;  //4
short c;//2
};
//进行整体对齐,最大类型为4=对齐系数4,所以按4整体对齐 1<4(对齐4) 4=4 2<4(对齐4)  所以4+4+4=12 
#pragma pack(2)
struct D {
    
    
char b; //1
int a;  //4
short c;//2
};
//进行整体对齐,最大类型为4>对齐系数n(2),所以按2整体对齐 1<2(对齐2)4>2(2的倍数) 2=2 所以2+4+2=8 
答案及解析:3 8 12 8
 
 
2. 有一个如下的结构体:
struct A{
    
    
 long a1;
 short a2;
 int a3;
 int *a4;
};
请问在64位编译器下用sizeof(struct A)计算出的大小是多少?
24
28
16
18
 
答案及解析:24
64位编译器下:指针8字节(一定不能忘记),题目不说默认4字节对齐
long a1;    //8
 short a2;  //2 8+2=10(不是4的倍数)对齐到4的倍数12
 int a3;    //4 4+12=16(4的倍数)
 int *a4;   //8 8+16=24(4的倍数)

猜你喜欢

转载自blog.csdn.net/weixin_45511599/article/details/104457272