西邮 Linux 兴趣小组 2021 纳新试题

西邮 Linux 兴趣小组 2021 纳新试题,第1张

西邮 Linux 兴趣小组 2021 纳新试题 1. 请试着解释其输出
int main(int argc , char *argv[]) {
    unsigned char a = 255;
    char ch = 128;
    a -= ch;
    printf("a = %d ch = %dn", a, ch);
}

结果:a = 127 ch = -128

`对a:先将a看作int,就是 0000 0000 0000 0000 0000 0000 1111 1111 ,然后截取char类型的长度,就是1111 1111(补码),因为无符号,原码:1111 1111,就是255,减去128得127。

对ch:char类型,8字节,128的原码就是1000 0000,这是个有符号型,所以输出,为-128.

2. 下面代码的运行输出结果是什么,并说说你的理解。
int main(int argc, char *argv[]) {
    char *str = "Xi You Linux Group 20";
    printf("%dn", printf(str));
    return 0;
}

结果:Xi You Linux Group 2021

        printf("%d",printf(str)), 是输出printf(str)的返回值,printf(str)的返回值是printf(str)中输出的字节数,"Xi You Linux Group 20"正好21个字节,所以输出了21,。

3. 这段代码的输出结果是什么?为什么会出现这样的结果?

int i = 2;
void func() {
    if(i != 0) {
        static int m = 0;
        int n = 0;
        n++;
        m++;
        printf("m = %d, n = %dn", m, n);
        i--;
        func();
    }else{
        return;
    }
}
int main(){
    func();
    return 0;
}

         这一题相同的类型,我以前的面试题分析写过了,就不过多写了,就是变量的生命周期和定义域的东西。 

4. 下面程序会出现什么结果?为什么会出现这样的结果? 
int main(int argc, char * argv[]) {
    char ch = 'A';
    int i = 65;
    unsigned int f = 33554433;
    *(int *)&f >>= 24;
    *(int *)&f = *(int *)&f + '?';
    printf("ch = %c i = %c f = %cn", ch, i, *(int *)&f);
    return 0;
} 

        对ch,ch直接输出A.

        对i,A的ascii正好是65

        对f,33554433>>24后为2,2+‘?’,?的ascii为63,加起来正好65;

这里的f强制换为int类型后在运算,输出,因为char是有符号型的.

 5.  下面代码的运行输出结果是什么,并说说你的理解.

        

int main(int argc, char *argv[]) {
    int a[2][2];
    printf("&a = %p t&a[0] = %p t&a[0][0] = %p n", &a, &a[0],&a[0][0]);
    printf("&a+1 = %p t&a[0]+1 = %p t&a[0][0]+1= %p n", &a+1,&a[0]+1, &a[0][0]+1);
    return 0;
}

        &a,%a[0],&a[0][0]指向的地址一样,都是数组的一个数的地址。

        &a+1是在&a[0][0]的地址上增加sizeof(a)的长度,&a[0]+1是在&a[0][0]的地址上增加sizeof(a[0])的长度,&a[0][0]+1是在&a[0][0]的地址上增加sizeof(a[0][0])的长度.

 运行结果:&a = 0x7ffe5aae4420     &a[0] = 0x7ffe5aae4420  &a[0][0] = 0x7ffe5aae4420 
&a+1 = 0x7ffe5aae4430   &a[0]+1 = 0x7ffe5aae4428        &a[0][0]+1= 0x7ffe5aae4424 

注意:你的运行结果可能和我不同,因为地址是使用时分配的,每次分配的可能不一样。

6. 下列程序的功能是什么?有什么问题,你能找出问题并解决它吗?        
int* get_array() {
    int array[1121];
    for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
        array[i] = i;
    }
    return array;
}
int main(int argc, char *argv[]) {
    int *p = get_array();
}

        警告:函数返回局部变量的地址。(我还没看,编译器就自己报出来了)

        函数不能返回局部变量的地址,因为,出了函数后地址中的值就会被抛弃,可能你调用完函数马上用不会有问题,但你在使用这个值和函数之间加一条占用地址的语句,就会出错。

        对于这种情况,可以用static局部静态变量来解决,或者从主函数传入地址。

int* get_array() {
    static int array[1121];
    for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
        array[i] = i;
    }
    return array;
}
int main(int argc, char *argv[]) {
    int *p = get_array();
}

7. 下面代码的运行输出结果是什么,并说说你的理解。

int main(int argc, char *argv[]) {
    char str[] = "XiyouLinuxGroup";
    char *p = str;
    char x[] = "XiyouLinuxGroupt106Fbamily";
    printf("%zu %zu %zu %zun", sizeof(str), sizeof(p),sizeof(x), strlen(x));
    return 0;
}

                结果:16 8 25 24

sizeof和strlen的区别:

        sizeof 是C 语言的一种单目运算符,strlen是个函数.

        sizeof以字节的形式给出 *** 作数的存储空间的大小,strlen 计算的是字符串的长度。

        sizeof()的()中不能调用函数。

        strlen是根据“”来判断是否结束的,所以strlen只能判断字符串.

 指针64位下都是8字节,32位下4字节,strlen会计算上“”.

8. 如下程序,根据打印结果,你有什么思考?
int add(int *x, int y) {
 return *x = (*x^y) + ((*x&y)<<1);
}
int a;
int main(int argc, char *argv[]) {
 int b = 2020;
 if(add(&b, 1) || add(&a, 1)) {
 printf("XiyouLinuxGroup%dn", b);
 printf("Waiting for y%du!n", a);
 }
 if(add(&b, 1) && a++) {
 printf("XiyouLinuxGroup%dn", b);
 printf("Waiting for y%du!n", a);
}

          ||是先判断左边的,如果为真就不再判断右边的,为假就判断右边的,只要有一个为真就为真。

        &&是先判断左边的,如果为假就不判断右边的,否则就判断,只有两个都为真,才会是真。

  9. 在下段程序中,我们可以通过第一步打印出 a 的地址,假如在你的机器上面打印结果 是 0x7ffd737c6db4;我们在第二步用 scanf 函数将这个地址值输入变量 c 中;第三 步,随机输入一个数字,请问最终输出了什么结果,你知道其中的原理吗?
void func() {
    int a = 2020;
    unsigned long c;
    printf("%pn", &a);
    printf("我们想要修改的地址:");
    scanf("%lx", &c);
    printf("请随便输入一个数字:");
    scanf("%d", (int *)c);
    printf("a=%dn",a);
}

        a的值将会被修改,因为a这个变量指向的地址里的值被赋给了c,然后a和c指向了同一块地址,所以修改c的值,也会同步修改a的值,修改a的值也会影响c.

(第十题问c语言源程序到可执行文件的被我吃掉了)

11. 请解释一下这行代码做了什么?

puts((char*)(int const[]){
    0x6F796958,0x6E694C75,0x72477875,
    0x3270756F,0x313230,0x00000A
    });

结果:XiyouLinuxGroup2021(小端)

                大小端,16进制的ascii码,19年,20年都有。

12. 请随机输入一串字符串,你能解释一下输出结果吗?

int main(int argc, char *argv[]) {
    char str[1121];
    int key;
    char t;
    fgets(str, 1121, stdin);
    for(int i = 0; i < strlen(str) - 1; i++) {
        key = i;
        for(int j = i + 1; j < strlen(str); j++) {
            if(str[key] > str[j]) {
                key = j;
            }
        }
        t = str[key];
        str[key] = str[i];
        str[i] = t;
    }
    puts(str);
    return 0;
} 

         这是字符串利用ascii码进行排序,按ascii码由小到大排序;

13. 用循环和递归求 Fibonacci 数列,你觉得这两种方式那种更好?说说你的看法。如果 让你求 Fibonacci 数列的第 100 项,你觉得还可以用常规的方法求解吗?请试着求 出前 100 项的值(tip 大数运算)。

        我先忙猜循环,因为递归调用函数,会极大影响效率,(C++中inline函数改善了这种情况)

然后就是写代码分析了:

long recursive(int n){
    if(n==1||n==2){
        return 1;
    }else{
        return recursive(n-1)+recursive(n-2);
    }
}

long loop(int n){
    if(n == 1 || n == 2)    
        return 1;
    long a = 1, b = 1, temp;  
    int i;
    for(i = 3; i <= n; i++) {
        temp = b;
        b = a + b; 
        a = temp;  
    }
    return b;
}

int main(){
    int a=10;
    scanf("%d",&a);
    long int c=recursive(a);
    printf("%ldn",c);
    long int b=loop(a);
    printf("%ldn",b);

    return 0;
}

可以看出,递归的时间复杂度是O(2^n),循环的则是O(n),可以看出循环的效率远高出递归。

对于第100个斐波那契数,长度超出 long long,只能用大数计数:

( 前几天刚看的求第1000位数,改一下正好能求第100个的值):

int main(){
    int fib[3][1005]={{0,0},{1,1},{1,1}};//三个斐波那契数:f(n),f(n-1),f(n-2),各一维数组第一个位为位数计数。
    int n=2;//n为第n位斐波那契数

    while (n < 100) {
        n += 1;
        for(int i=1;i <= fib[(n - 1) % 3][0];i++){
            fib[n%3][i]=fib[(n-1)%3][i]+fib[(n-2)%3][i];// 对应位置上的数字相加
        }
        fib[n%3][0]=fib[(n-1)%3][0];//将位数及时移动过来
        for (int i = 1; i <= fib[n % 3][0]; ++i) { //处理进位
                if (fib[n % 3][i] < 10) continue;
                fib[n % 3][i + 1] += fib[n % 3][i] / 10;
                fib[n % 3][i] %= 10;
                fib[n % 3][0] += (i == fib[n % 3][0]);
            }
    }
    for(int i=1;i<=fib[n % 3][0];i++){
            printf("%d",fib[n%3][i]);
    }
    printf("n");
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5658538.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存