代码改变世界

基础题

2019-10-11 17:44  BigBigDream  阅读(331)  评论(0)    收藏  举报

1. 1000G硬盘容量相当于1000M硬盘的多少倍?

在计算机中:

1GB=1024MB

换算即可得到

1024倍

但硬盘的厂家通常是按照1GB=1000MB进行换算的!!!

这时为1000倍

 

2.下面程序输出的结果是什么?为什么?

int main(void)

{

  int a = 2147483647;

  int b = 1;

  printf("%d",a+b);

  return 0;

}

 

 

运行的结果

(1)我们知道int类型在C语言中占4个字节,即32个二进制位。
当表示正数时,最高位为符号位(符号位为0),最大的正数是 0111 1111 1111 1111 1111 1111 1111 1111 即2^31 -1 = 2147483647
当表示负数时,最高位为符号位(符号位为1),最小的负数是 1000 0000 0000 0000 0000 0000 0000 0000

负数在计算机中是以补码的形式存储的,C语言规定 1000 0000 0000 0000 0000 0000 0000 0000 的补码为-2147483648

而该题的运行结果也与上述有关

(2)我们可以看出,当a与b相加后,按照我们的想法,它的值应该为2147483648,很明显该值已经超过了int型的最大数2147483647

已经造成了数据的溢出!!

(3)那为什么输出的结果为负数呢?

  这就与(1)有关了,0111 1111 1111 1111 1111 1111 1111 1111+1=1000 0000 0000 0000 0000 0000 0000 0000,(补码的计算,是原码的基础上,

符号位不变, 其余各位取反, 最后+1),而它所对应的补码为-2147483648,这就是它输出-2147483648的一些原理。

3. 分析代码,说出运行结果:

int main(void)
{
     int x = 1, y = 1, z = 1;
     y = (++ x) + (x ++) + (++ x);
     z = (-- x) + (x --) + (++ x);
     printf("%d %d %d", x, y, z);
 }

按照正常的运算逻辑,y=2+2+4=8,z=3+3+3=9,x的最终值为3!

这段代码我尝试的运行结果

1.Dev-C++下的运行结果

 

 

2.Visual Studio 2019下的运行结果

 

 

 3.在windows系统DOS命令行下用gcc 编辑运行结果

 

 

 

在这里只能说明每个编译器的实现方式可能不同,我觉得只需要理解x的变化即可,++x的意思为先进行自增运算然后将值传入进行运算,x++则是先传入进行运算后进行自增即可!

4.分析下面的程序,谈谈你的理解:

int swap(a, b)
{
     int t = a;
   a = b;
   b = t; } int main() { int a = 1, b = 2; swap(a, b); }

看这段程序,我们知道它想要表达的意思是将a,b的值交换,但却犯了一些错误.

在使用函数时,我们得记住,值得传递是单向的。且由实参传给形参,而不能由形参传给实参,实参和形参在内存中占有不同的存储单元!

上面这段程序经过运行

#include<stdio.h>

int swap(int a, int b)
{
    int t = a;
    a = b;
    b = t;
 } 
int main()
{
     int a = 1, b = 2;
     swap(a, b); 
     printf("%d,%d\n",a,b);
}
//输出的结果为1,2

我们可以这样修改,利用指针实现值得交换

#include<stdio.h>

int swap(int *p1, int *p2)
{
    int t;
    t = *p1;
    *p1 = *p2;
    *p2 = t;
 } 
int main()
{
    int a = 1, b = 2;
    swap(&a,&b); 
    printf("%d,%d\n",a,b);
}
//执行的结果为2,1

5.你用过strlen和sizeof函数吗?它们的作用是什么?它们的区别又是什 么?

(1)strlen计算字符串str的长度,但不包括终止空字符, 参数为char *类型。

sizeof运算对象可以是任何变量或类型,计算结果为该变量或类型占的实际长度(内存字节数),

sizeof对指针变量进行操作的时候返回的则是指针变量本身所占得空间,在64位机的条件下一般都是8。

(2)区别

1.strlen为C语言库函数之一;sizeof为一个运算符,是C语言关键字之一。

2.数组做sizeof的参数不退化,传递给strlen就退化为指针了

3.sizeof可以用类型做参数,strlen只能用char*做参数,且必须是以”\0”结尾的

下面是一段测试的截图,可以很好的说明以上内容!

 

 

 6.你所了解过的循环有哪些?它们有什么区别呢?

for循环

for(表达式1;表达式2;表达式3){ 循环体;

while循环

while(表达式){
循环体;

do while 循环

do{
循环体;//或者称为语句块
}while(表达式);

区别:

用while循环和do while循环时,循环变量初始化操作应在while和do while 语句之前完成, 而for 语句可以在表达式1中实现循环变量的初始化。

 

使用do while 时,无论判断条件成不成立,循环体都会执行一次,下面是一个测试代码的截图

 

 

 7. 语言中的内存是怎么分配的?你是不是真的了解呢?

#include <stdio.h>
struct s1{
char a;
int b;
double c;
union {
float d;
short e;
}
};
int main(void){
printf("%d\n",sizeof(struct s1));
return 0;
}

这段代码涉及的知识点是有关于sizeof下结构体所占内存大小还有字节对齐的知识!

上述代码的执行结果为24,按照我们正常思考,char 1个字节 int 4个字节 double 8个字节  union取其内部所占内存长度最长的成员float, 4个字节 1+4+8+4=17,很显然,不是24

为什么结果为24呢?

这时我们就得知道一个概念:偏移量 ,它指的是结构体变量中成员的地址和结构体变量地址的差!

结构体的大小等于最后一个成员的偏移量加上最后一个成员的偏移量加上最后一个成员的大小

计算的过程还得符合以下原则:

1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

现在我们来看上面的结果为什么为24,

第一个成员a的偏移量为0,第二个成员的偏移量为第一个成员的偏移量加上第一个成员的大小0+1=1,其值为1,我们发现,现在这个偏移量不满足原则1)

那就要进行填充,使其为第二个成员的整数倍,填充3即可,此时第三个成员的偏移量为1(第一个成员的大小)+3(填充)+4(第二个成员的大小)=8

第四个成员的偏移量为8(第三个成员的偏移量)+8(第三个成员的大小)=16,到第五个成员时,可知共同体的大小为其内部所占内存长度最长的成员,float ,

结构体的大小为16(最后一个成员的偏移量)+4)(最后一个成员的大小)=20,嘿嘿,这时候。又发现不满足原则2),这时候又需要填充,填充4即可符合所有的原则,此时结构体的大小为20+4=24

最后说一句,其实在不同的的平台下这个值可不一定是24,在Linux下用gcc编译的结果为20!学无止境,还需要我们继续学习呀!

8. 下面的程序会输出什么?你是怎么想的?

 

#include <stdio.h> 
int main(void)
{ 
    char ch[][5]={'I','O','I','H','F',' B','D','L','B','V', 'N','C','P','L','K', 'F','Y','O','Z','S', 'D','O','X','C','V', 'N','F'};
    printf("%c%c%c%c\n",ch[0][18],ch[4][-4],ch[1][7],ch[5][-2]); 
    return 0; 
}

 

第一眼看这个程序,什么鬼??这能通过编译??结果......还真可以!!说实在的,还真没见过这样去玩二维数组的!这时候想起,老师讲过这样一个概念

(实际上并不存在多维数组,所谓的多维数组本质上是用一维数组模拟的)

那么我们现在来讨论一下

1)首先ch这个数组名代表着什么?

答:指向包含五个元素的数组的指针

这样说有点难懂,简单配个截图(画的有点丑!!!)

 

 

接下来再用代码来验证一下!

 

 

 刚好跨度是20个字节也就是5个位置(每个位置是一个int(4个字节))

 

 

2)*(ch+1)这个是什么意思呢?**(ch+1)呢?

*(ch+1)代表了ch[1][0]的地址;

**(ch+1)代表了ch[1][0]所指的值

接下来我们来测试一下,下面是测试的截图!

 

 

 没有错误,和判断的一样;

接下来解释,为什么会有题目中那样的输出呢?

 

{                 'I','O','I','H','F',
                  'B','D','L','B','V',
                  'N','C','P','L','K',
                  'F','Y','O','Z','S',
                  'D','O','X','C','V',
                  'N','F'                  };

输出结果为  ZYPC

ch[0][18]相当于*(*(ch+0)+18),它输出结果为Z

ch[4][-4]相当于*(*(ch+4)+(-4)),它的输出结果为Y

ch[1][7],相当于*(*(ch+1)+7)它输出的结果为P

ch[5][-2],相当于*(*(ch+5)+(-2))它输出的结果为C

 

 

 这样就大致了解了题中这段代码!

9.尽可能多的说出你所了解的排序算法,它们的时间复杂度和稳定性又如何?

 

 排序算法这块,目前还没有深入的学习,只是简单的了解最基础的冒泡和选择排序!

 

10. 给出如下定义:

 

struct node{
int a;
int b;
int c;
}; struct node s = {3,5,6};
struct node *pt = &s;

 

 

 

要求:用不同的方式输出 5
代码如下,只是简单地输出,一个是通过结构体直接读取数据的方式输出,另一个是结构体指针指向s,利用指针指向的方式输出,最后.......直接输出5!!!

 

#include<stdio.h>
/**
    要求:用不同的方式输出 5
*/
struct node
{
    int a;
    int b;
    int c;
};
struct node s = {3,5,6};
struct node *pt = &s;

int main(void)
{
    printf("%d\n",s.b);
    printf("%d\n",pt->b);
    printf("5\n");
    printf();
    
}