C语言练习题(10)求函数返回值,传入 -1 ,则在64位机器上函数返回(非常详细的讲解)

1:求函数返回值,传入 -1 ,则在64位机器上函数返回( )

int func(int x)
{
int count = 0;
while (x)
{
count++;
x = x&(x - 1);//与运算
} 
return count;
}

A: 死循环 B: 64 C: 32 D: 16


解析 C

-1 原码 1000000 00000000 00000000 00000001
其补码 1111111 11111111 11111111 11111111

-2 原码 1000000 00000000 00000000 00000010
反码 1111111 11111111 11111111 11111101
补码 1111111 11111111 11111111 11111110

-1&-2 1111111 11111111 11111111 11111110
首位不变,其他取反+1其原码为-2

-3 原码 1000000 00000000 00000000 00000011
反码 1111111 11111111 11111111 11111100
补码 1111111 11111111 11111111 11111101

-2&-3 1111111 11111111 11111111 11111100
首位不变,其他取反+1其原码为-4

可以看出每次异或都将最后的一位变为0,那么进行32次,全部变为0,跳出while循环 count=32;

2:读代码选结果( )

int count = 0;
int x = -1;
while(x)
{
count++;
x = x >> 1;
}
printf("%d",count);

A: 1 B: 2 C: 32 D: 死循环,没结果

解析 D

-1 补码 11111111 11111111 11111111 11111111
x>>1 11111111 11111111 11111111 11111111
左移最高位补的是符号位,因此-1的符号位是1,所以最高位衡补1,造成死循环

3:下述赋值语句错误的是( )

A: a = (b = (c = 2 , d = 3)) B: i++ C: a/b = 2 D: a = a < a + 1


解析 C

A:先看逗号表达式 d=3 将d的值给b 再将b的值给a

B:i++最常见的一种写法

C:a/b不能作为一个变量

D:a < a + 1的结果为1(真),否则为0(假)。最后将这个结果赋给a变量。

4:若有 int w=1, x=2, y=3, z=4; 则条件表达 w < x ? w : y < z ? y : z 的值是( )

A: 1 B: 2 C: 3 D: 4

解析 A

w 判断 (为真) ( 为假)
首先,计算w < x,即1 <2,这个条件为真,所以返回w的值,即1。
以最外层的表达式为主。

5:以下程序运行后的输出结果是( )

int main()
{
int a=1,b=2,m=0,n=0,k;
k=(n=b<a)&&(m=a);
printf("%d,%d\n",k,m);
return 0;
}

A: 0,0 B: 0,1 C: 1,0 D: 1,1

解析 A

k= (n=b

b

但是m=a为()中的表达式,不做实际运算,所以m仍为0;

6:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

核心代码版:

int Add(int a, int b ) 
{
   while (b != 0) 
   {
        int sum = a ^ b;
        int carry = (a & b) << 1;
        a = sum;
        b = carry;
    }
    return a;
}

完整代码版:

#define _CRT_SECURE_NO_WARNINGS 1
#include 
int Add(int a, int b)
{
    while (b != 0)
    {
        int sum = a ^ b;
        int carry = (a & b) << 1;
        a = sum;
        b = carry;
    }
    printf("%d", a);
}

int main()
{
    int a = 0, b = 0;
    scanf("%d %d", &a, &b);
    Add(a, b);

return 0;
}

解析:

  1. while 循环:进入循环后,我们将会一直执行下去,直到 b 的值变为 0。
  2. 异或操作:int sum = a ^ b;,我们通过异或操作(^)得到两个整数的无进位和。 例如,对于二进制数 5 和 3(101 和 011),异或操作将会得到二进制数 6(110)。
  3. 与操作和左移操作:int carry = (a & b) << 1;,我们通过与操作(&)和左移操作(<<)得到了两个整数的进位值。与操作将会得到两个整数的公共位,并且左移操作将将这些公共位移到正确的位置上。
    例如,对于二进制数 5 和 3(101 和 011),与操作将会得到二进制数 1(001),然后左移操作将会得到二进制数 2(010)。
  4. 更新 a 和 b:a = sum; b = carry;,我们将无进位和和进位值分别赋给了 a 和 b。这样,a 的值变为了无进位和,b 的值变为了进位值,为下一次循环做准备。
  5. 继续执行下一次循环,直到 b 的值变为 0。每次循环都会将进位值不断地传递下去,直到没有进位为止。通过这个循环过程,我们实际上是将加法拆分成了无进位和和进位值的计算,并且通过循环迭代将进位值不断地传递下去。最后,我们得到的
    a 的值就是两个整数的和。
  6. 返回 a:当 b 的值变为 0 时,我们跳出循环并返回 a,它的值就是两个整数的和。

如果看了解析还是不太明白的话,大家自己在纸上拿两个数字运算一边就可以明白啦,毕竟还是要动动手的嘛。

7:给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例 1: 输入:nums = [4,3,2,7,8,2,3,1] 输出:[5,6]

示例 2: 输入:nums = [1,1] 输出:[2]

核心代码版:

#define _CRT_SECURE_NO_WARNINGS 1
#include 
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
{
    int* res = (int*)malloc(sizeof(int) * numsSize);
    int i, j = 0;
    for (i = 0; i < numsSize; i++)
    {
        res[i] = 0;
    }
    for (i = 0; i < numsSize; i++)
    {
        res[nums[i] - 1] =  res[nums[i] - 1]+1;
    }
    for (i = 0; i < numsSize; i++)
    {
        if (res[i] == 0) res[j++] = i + 1;
        *returnSize = j;
    }
    return res;
}

完整代码版:

#define _CRT_SECURE_NO_WARNINGS 1
#include 
int* findDisappearedNumbers(int* nums, int numsSize, int* returnSize)
{
    int* res = (int*)malloc(sizeof(int) * numsSize);
    int i, j = 0;
    for (i = 0; i < numsSize; i++)
    {
        res[i] = 0;
    }
    for (i = 0; i < numsSize; i++)
    {
        res[nums[i] - 1] += 1;
    }
    for (i = 0; i < numsSize; i++)
    {
        if (res[i] == 0) res[j++] = i + 1;
        *returnSize = j;
    }
    return res;
}

int main()
 {
    int n = 0;
    scanf("%d", &n);
    int nums[10001] = { 0 };
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &nums[i]);
    }
    int returnSize;

    int* result = findDisappearedNumbers(nums, n, &returnSize);

    printf("消失的数字:");
    for (int i = 0; i < returnSize; i++)
    {
        printf("%d ", result[i]);
    }
    printf("\n");

    free(result); // 释放内存

    return 0;
}

解析:

主函数的部分非常简单,就是定义数组和数组长度,相信大家都能看懂,我就不在这里讲啦!
在核心代码中,使用malloc函数,这个函数大家不理解的话可以看我之前的博客哦,就是开辟一块空间。
①首先,定义了一个长度为numsSize的整型数组res,并将其初始化为0。

②然后,遍历nums数组,将对应的res数组位置上的数值加1。这一步的目的是统计每个数字出现的次数。

nums[i]表示nums数组中的第i个元素的值。
nums[i]-1表示将该元素值减1,目的是将其作为res数组的索引值,因为数组的索引从0开始。
res[nums[i]-1]=res[nums[i]-1]+1表示将res数组中相应索引位置的值加1。这个操作是在进行计数统计。
.

③接下来,再次遍历res数组,如果某个位置上的数字为0,说明该位置对应的数字在nums数组中缺失。将该缺失的数字添加到返回的数组之中。

遍历数组res的每一个元素,从下标0到numsSize-1。
如果res的当前元素值为0,表示该位置缺失了一个数。
将i+1赋值给res中下标为j的位置,然后将j的值加1。
最后,将j赋值给returnSize,表示缺失数的个数。
.

④最后,将返回的数组长度记录在returnSize指针所指的位置,并将res数组返回。

你可能感兴趣的:(练习题,c语言,算法,开发语言)