海康威视超新星笔试题C语言篇。
题目一
求下面这段代码的运行结果
#include <stdio.h>
#define M 3
#define N M + 2
#define SUM(M, N) (M + 1) * N / 2 + N
#define DEL(M, N) (N + 1) * N / 2 - 2 * M
int testfunc(int flag) {
int ret = -1;
switch (flag) {
case 0:
ret += SUM(M, N);
break;
case 1:
ret += DEL(M, N);
default:
ret += SUM(M, N);
break;
}
return ret;
}
int main(void) {
int ret1 = testfunc(0);
int ret2 = testfunc(1);
printf("%d,%d\n", ret1, ret2);
return 0;
}
大家在看这道题的时候认为结果应该是啥?
14 8 ?
14 23?
不对,都是错的。为什么呢?再仔细看一下这一题。有两个点需要注意。
第一点:宏定义
在C语言中,宏定义的值会在编译阶段直接被替换,仔细看一下题目中N的宏定义,大家会发现它的值为M+2 ,在这里就得想一下#define的用法了,#define在C语言中是预处理指令,在程序执行的过程中,只起到文本替换的作用,而不运算,所以SUM=(4+1)x 3 +2/2 +5=18。
第二点:case语句的格式。
大家仔细观察就能发现第二个case语句没有break,那么代码机会接着运行。
所以最终的结果是17 30。
题目二
求下面这段代码的运行结果
#include <stdio.h>
int main(void) {
int a[][3]= {{0,1},{2,3,3},{5,6},{7}};
printf("%d\n", a[2][1]);
}
这道题很简单,就是考二维数组的基本概念。二维数据第一维表示行数,第二维表示列数,所以
a[2][1],表示第二行第一列这个元素。那么我们就在二维数据的元素中直接查找。在二维数据中,没有的数据用0补齐,所对不要用后面的元素补齐。第二行第一列的元素应该为6。
题目三
求下面这段代码的运行结果
#include <stdio.h>
#include <stdint.h>
typedef struct{
uint16_t a;
uint16_t b;
uint16_t res[10];
} CFG;
int main(void) {
CFG *p;
printf("%d\n", sizeof(p));
}
大家在做这道题的时候觉得答案是多少?
8? 24?
错,都错了。
在这里我们需要注意两个地方
第一:32位系统
第二:打印的是指针的大小还是结构体的大小。
注意到以上两点很容易知道,我们打印的是在32位系统下指针的大小。在这里需要知道指针的基本概念。
指针的大小等于操作系统的地址总线宽度,因为指针指向的是地址。所以,在32位系统中,32位就是4个字节,大小位4,在64位系统中,大小就为8。
所以这题的运行结果是4。
题目4
求下面这段代码的运行结果
char str[] = "hikvision";
int sizeStr = sizeof(str);
printf("%d\n", sizeStr);
这题很简单,就是需要注意字符串数组最后一个元素为‘/0’,结果为10。
题目五
uint16_t 类型的变量,赋值为 0x1234,要求分别在小端(Little-Endian)和大端(Big-Endian)
存储的机器上,该变量在低地址空间存放的第1字节的数值是什么?
A. 0x12 和 0x34
B. 0x12 和 0x12
C. 0x34 和 0x34
D. 0x34 和 0x12
这题很简单,只需要了解大小端的定义即可。
大端:高位数据存放在低位地址,低位数据存放在高位地址
小端:高位数据存放在高位地址,低位数据存放在低位地址
了解定义之后直接秒选D
题目六
A :
void clear_value(const int *p) {
*p = 0; // 错误:试图修改 const 指针指向的值
}
B:
#include <stdio.h>
typedef void (*P_FUNC)(void *data, unsigned int data_len);
void print_data(void *buf, unsigned int len) {
char *p = buf;
if (NULL != p) { // 正确:检查指针是否为NULL
printf("Welcome to 解答\n", p); // 打印欢迎信息(注:格式字符串无占位符)
}
}
int main() {
char *str = "HIK ROBOT";
P_FUNC print_string = print_data;
print_string((void *)str, 10); // 正确:类型转换和指针传递
return 0;
}
C:
#include<stdio.h>
int main(void) {
int i = 0;
char a[10] = {1,2,3,4,5,6,7,8,9,10};
char b[10];
char *p = NULL;
p = b;
for(i=0; i<10; i+1) {
p+i = a+i;
printf("b[i]%d\n", b[i]);
}
return 0;
}
D:
int *foo(void) {
int val = 100; // 局部变量
for (int i = 0; i < 100; i++) {
val++;
}
return &val; // 错误:返回局部变量的地址
}
A选项:const int *p
表示指针指向的值是常量,不可修改。
B选项:正确
C选项:左侧 p+i
是地址计算结果,不可直接赋值。正确应需改为
*(p + i) = *(a + i);
D选项:首先看函数,该函数为指针函数,返回值是一个为int类型的指针。再看变量val,该变量为局部变量,且未加static修饰,作用完内存会被系统自动回收,其地址变得无效。
对于函数指针和指针函数的区别:主要就是一个是指针,一个是函数。
函数指针是指向函数的指针类型变量,用于间接调用函数。
指针函数是一个函数,返回值是一个指针类型的变量。
函数指针 vs 指针函数对比表
函数指针
int add(int a, int b) { return a + b; }
int (*func_ptr)(int, int) = add; // 函数指针
int result = func_ptr(2, 3); // 通过指针调用
指针函数
int *create_array(int size) {
return malloc(size * sizeof(int)); // 返回动态数组指针
}
int *arr = create_array(10); // 调用指针函数
后续还会有海康威视的在线编程题,未完待续。