笔试面试-c语言题1

1.简述const的作用,const与#define相比,有何优点。

表示定义一个常量,其值在程序的允许期间不可改变。

优点:

1.类型更加安全,const是有类型的常量,编译器会进行类型检查 define 是简单的文本替换 可能会导致未定义的行为

2.作用域,const可以作用在特定的代码块中 define宏定义是全局的 可能会导致命名冲突

3.调试友好,const调试可以识别常量的名称 define不可见

4.使用表达式,const用于初始化时表达的计算 define只能使用简单的常量或表达式

5.const占空间 define在预处理期间替换 不占用空间

2. 头文件中的 #ifndef #define #endif 干什么用?

1.防止头文件的重复包含,如果一个头文件被多个源文件包含,或同一个源文件多次包含同一个头文件,可能导致重复定义的错误。该指令确保包含的内容只被编译一次

2.提高编译效率,确保每次只编译一次 更快处理源文件 提高编译效率

3.what's the difference among the data types "char *p",
"const char *p", "char * const p"and"const char *const p" ?

1.char *p

指向char类型的指针

既可以修改p指向的地址 又可以修改p指向的内容

2.const char *p

指向常量char 的指针p 常量指针 指向的内容不可改变 指向的地址可以改变

3.char * const p

指向char的常量指针p 指针常量 指向的方向不可改变 指向的内容可以改变

4.const char * const p

指向常量的常量指针 指向的方向和内容都不可改变

4.局部变量能否和全局变量重名.

可以 局部变量优先级高于全局变量 如果想要使用全局变量则在全局变量前加作用域符号::(c++) 使用extern(c)

5.请简述typedef int(*FUN)(int x, int y)及其作用

定义一个指向两个参数为int并且返回值为int 类型的函数指针

使用typedef为该指针别名为 FUN

作用:使函数指针的声明与使用更加简洁和直观

6.C语言中的main函数返回值有什么用?

返回值类型通常返回一个整型 int

指示程序退出状态 返回值为0 表示程序成功退出 返回值非0 表示程序出现错误或异常

7.VC中有哪些方法避免C编程中的头文件重复包含?
1.宏预处理指令

#ifndef HEADER_FILE_NAME_H // 检查宏是否定义 #define HEADER_FILE_NAME_H // 定义宏

// 头文件内容

#endif // HEADER_FILE_NAME_H // 结束判断

2.#pragma once
8.将程序移植到不同的32位cpu中,经常出现结构字节对齐和大小端的问题,有哪些方法避免?

结构体字节对齐问题,避免方式:

1.手动控制字节对齐 如按照4个字节对齐 #pragma pack(4)

大小端问题:

1.识别大小端是否一致 写一个判断大小端的函数 如果大小端不一致 写一个转换大小端的函数 进行转换

\9. sizeof

struct

{

short a;

long b;

char c;

}d;
sizeof(d)为什么在不同的平台上得到的值不一样?

平台问题 x86 long 4字节 x64 long 8字节

字节对齐问题

10.strcpy()为什么会造成缓冲区溢出?可用哪个函数代替?

strcp(a,b);如果b的长度大于a能存储的最大长度 就会产生缓冲区溢出 该函数没有识别目标缓冲区长度的功能

strcpy_s(a,len,b);

\11. strcat的效率问题,有没有更好的解决方案.

如果知道前一个字符串长度就可以直接从尾部开始拼接

建议答:将前一个字符串长度以参数传入

解决方案 string += ...;

12.Heap和Stack有什么区别

13.请简述大端字节序和小端字节序的概念,设计一个小程序来判断当前操作系统的字节序。

多字节数据在内存的存储方式

大端字节序:高位字节存储在低地址,低位字节存储在高地址

例如,一个32位整数 0x12345678 在大端字节序中的存储顺序为:12 34 56 78

小端字节序:低位字节存储在低地址,高位字节存储在高地址

例如,同一个32位整数 0x12345678 在小端字节序中的存储顺序为:78 56 34 12

#include <stdio.h>
​
int main() {
    unsigned int num = 0x12345678;
    unsigned char *byte = (unsigned char *)&num;
​
    if (byte[0] == 0x78) {
        printf("Little-endian\n");
    } else if (byte[0] == 0x12) {
        printf("Big-endian\n");
    } else {
        printf("Unknown endianness\n");
    }
    
    return 0;
​
}

14.全局变量和static变量什么区别

1.作用域:

全局变量作用域是全局的,其他源文件可以通过extern访问该变量

static修饰全局变量 该变量的作用域被限制在当前的文件,其他文件无法访问

static修饰局部变量,该变量的作用域是局部的

2.生命周期: 全局变量:生命周期是整个程序运行期间,从程序启动到程序结束存储在全局/静态区

static:修饰全局变量,生命周期与全局变量相同

修饰局部变量,生命周期延长到整个程序运行期间,作用域仍然是局部的

3.链接属性:

    • 全局变量

      • 默认是外部链接的,即其他文件可以通过 extern 关键字访问。

      • 如果使用 static 修饰全局变量,则变为内部链接,只能在当前文件中访问。

    • static 变量

      • 如果 static 修饰全局变量,则该变量是内部链接的,只能在当前文件中访问。

      • 如果 static 修饰局部变量,则该变量是无链接的,只能在定义它的函数或代码块内访问。

15.二进制数11101101转换为十八进制数是多少?
16.在函数体内声明[1] char *str = "abc";和 [2] char str[] = {'a','b','c'}有什么区别
17.strcpy,memcpy,sprintf的区别
1. strcpy
char *strcpy(char *dest, const char *src);
  • 功能:用于复制字符串。

  • 特点

    • src 指向的字符串(包括结束符 \0)复制到 dest 指向的内存中。

    • 复制过程会一直进行,直到遇到 src 中的 \0 为止。

    • 不检查 dest 的内存大小,可能导致缓冲区溢出。

      char src[] = "Hello";
      char dest[10];
      strcpy(dest, src); // dest 现在包含 "Hello"
      ​
  1. memcpy

  • 功能:用于复制内存块。

  • 原型

    void *memcpy(void *dest, const void *src, size_t n);
  • 特点

    • src 指向的内存地址开始,复制 n 个字节到 dest 指向的内存地址。

    • 不关心数据的类型或内容,只是简单地按字节复制。

    • 不检查 destsrc 的内存是否重叠。如果内存重叠,行为是未定义的。

  • 使用场景:复制任意类型的数据(如数组、结构体等)。

int src[] = {1, 2, 3, 4};
int dest[4];
memcpy(dest, src, sizeof(src)); // dest 现在包含 {1, 2, 3, 4}
  1. sprintf

  • 功能:用于格式化字符串并写入缓冲区。

  • 原型

    int sprintf(char *str, const char *format, ...);
  • 特点

    • 将格式化的字符串写入 str 指向的缓冲区。

    • 类似于 printf,但输出结果存储在缓冲区中,而不是打印到标准输出。

    • 不检查缓冲区的大小,可能导致缓冲区溢出。

char buffer[50];
int num = 123;
sprintf(buffer, "The number is %d", num); // buffer 现在包含 "The number is 123"

18.define的使用

(1)使用define定义一年有多少毫秒

#define mcount_per_year (365x24x60x60x1000)

(2)使用define定义max函数

#define max(a,b) ((a)>(b)?(a):(b))

(3)define中为何经常会使用 do{ }while(0);来包装多条语句代码

避免宏展开时的语法错误。

避免宏展开时的分号问题。

提高宏的兼容性和可读性。

19.实现一个死循环

while(1);

20.什么是预编译

由预处理器在编译器中对源代码进行处理,生成一个经过修改的源代码文件,供编译器使用

任务:

  1. 宏展开:处理 #define 定义的宏,将其替换为实际的值或代码。

  2. 文件包含:处理 #include 指令,将指定的头文件内容插入到当前文件中。

  3. 条件编译:根据 #if#ifdef#ifndef#else#elif#endif 等指令,选择性地编译代码。

  4. 删除注释:删除源代码中的所有注释。

  5. 处理特殊指令:如 #pragma#error#line 等。

21.#include<filename.h>和#include"filename.h"有什么区别?

优先在系统路径找

优先当前文件目录找这个文件 找不到再在系统路径找

22.写出三种交换两个int 变量a 和 b的方法:

1.____a= a^b ; b=a^b ; a= a^b; (a^=b; b^=a;a^=b;)

2.____a = a+ b;b = a-b;a = a-b;

3.____int tmp = a; a = b; b = tmp;

23.若x,y均是int型变量,则执行以下语句后,写出x,y的值 x=10 y = 6

for(y = 1,x = 1;y<=50;y++)

{

if(x>=10)break;

if(x%2 == 1)

{

x+=5;

continue;

}

x-=3;

}

24.写出以下代码段的输出结果

void swap(int m,int n)

{

int temp;

temp = m;m = n;n = temp;

}

main()

{

int m = 7,n = 5;

swap(m,n);

printf("m = %d,n = %d\n",m,n);

}

输出结果___m=7,n=5_________

25.请说明下面例子中const的用途()

\1) const int d = 100;__定义一个只读变量_________

2)const char *pStr1 = "ABCD";__内容不可改________

3)char *const pStr2 = "abcd";______方向不可改____

4)int func1(int value)const; ______定义常函数_____

26.写出以下程序的运行结果_____________
int count(int data)
​
{
​
int mask = 1;
​
int i,count = 0;
​
for(i = 0;i<sizeof(data)*8;i++)
​
{
​
if(data &mask)
​
{
​
count++;
​
}
​
mask<<=1;
​
}
​
return count;
​
}

data = 0x3; count =____2_________

data = 0x12345678;count = ____13_______

1. data = 0x3
  • 0x3 的二进制表示为:0000 0000 0000 0000 0000 0000 0000 0011

  • 其中 1 的个数为 2

  • data = 0000 1101 mask = 0000 0001 ------------------ & result = 0000 0001 (非 0)

2. data = 0x12345678
  • 0x12345678 的二进制表示为:0001 0010 0011 0100 0101 0110 0111 1000

  • 其中 1 的个数为 13

27.下面程序的运行结果是__19_________

#define ADD(a+b) a+b

int main()

{

printf("%d\n",5ADD(3+4)); 5x3+4

}

28.在C语言程序中,要给绝对地址0x100赋值,我们可以用:

(unsigned int)0x100 = 1234;

那么,要是想让程序跳转到绝对地址0x100的位置上执行。怎样用一段代码实现_____________

void jump_to_address(void) {
    // 定义一个函数指针,指向绝对地址 0x100
    void (*func_ptr)() = (void (*)())0x100;

    // 调用函数指针,跳转到 0x100 执行
    func_ptr();
}

int main() {
    jump_to_address();  // 跳转到绝对地址 0x100 执行
    return 0;
}

29.在C语言中,若要定义一个只允许本源文件中所有函数适用的全局变量,则该变量应该加关键字()修饰。

static

30.请问执行完下面的程序后x[0]至x[5]的值应为__836475_____
int x[6] = {5,7,4,6,3,8};

int i,k,t;

for(i = 0;i<5;i++)

{

for(k=(i+1);k<6;k++)

{


t = x[i];

x[i] = x[k];

x[k] = t;

}

}

31.试着写出结果及原因
unsigned char endian[2] = {1,0};

short x;

x = *(short*)endian;

代码运行后,x的值是多少? 

32.在 int b = { {1} ,{3 ,2},{4, 5 ,6},{0}};中 sizeof(b)是多少()

48

4行3列 4x3x4

33.请写出下面代码的输出结果。__2.5_________
void main(void)

{

int a[5] = { 1, 2, 3, 4, 5, };

int *ptr = (int*)(&a + 1);

printf("%d,%d", *(a + 1), *(ptr - 1));

}

34.在64位机器下的输出为__80__.

int(*p[10])(int);

fprintf(stderr, "%d", sizeof(p));

指针数组 10个Int指针

35.在little-endian机器,以下代码的输出是__8__.
union

{

int i, j;

char a, b;

}x;

int main(void)

{

x.a = 1;

x.b = 2;

x.j = x.a + x.b;

x.i = x.a + x.j;

 

printf("0x%x\n", x.i); 

return 0;

}
36 .如果x = 2014下面函数的返回值是__6____.
int fun(unsigned int x)

{

int n = 0;

while (x&255)

{

n++;

x = x&(x - 1);

}

return n;

}

37.

#include <stdio.h>

main()

{

FILE *fp;

int i, a[4] = { 1, 2, 3, 4 }, b;

fp = fopen("data.dat", "wb");//以二进制写的形式打开这个文件并给fp赋值,如果文件没有就创建,如果有,就清空

for (i = 0; i < 4;i++)

{

fwrite(&a[i], sizeof(int), 1, fp);//从这里帮忙解释一下

将a[i] 写入fp指向的文件流,每次写sizeof(int)个字节,写一次

}

fclose(fp); //文件中是 1,2,3,4

fp = fopen("data.dat", "rb");

fseek(fp, -2L * sizeof(int), SEEK_END);//从这里帮忙解释一下

将fp指向的文件流 从文件末尾向文件头跳转2L*sizeof(int)个位置 倒数第二个位置

fread(&b, sizeof(int), 1, fp);//从这里帮忙解释一下

将fp指向的文件流里读取一次,每次读取sizeof(int) 个字节 写入文件b

fclose(fp);

printf("b = %d\n", b);

}

答:____3________

38.程序的局部变量存在于__栈区___中,全局变量存在于__全局区中,动态申请数据存在于__堆区__中。

39.若一个视频中图像分辨率为1920 * 1080,每像素采样精度为16 - bit,每秒25帧图像,则每秒图像占内存______byte 25x2x1920x1080

(所有数据连续存放)。

40.请写出”得到两参数中较小值“的宏:

#define MIN(a,b)__((a)<(b) ? (a): (b))______

41.请写出”判断是否为2的幂次“的宏:

#define IS_POWER_OF_2(a)__________

(a)&&(((a)&((a)-1))==0)

42.int16_t x = 32767; x++; printf("%d", x);

输出的结果为__-32768_____

43.a = 1; a += ++(a++);此时a的值为多少。

a++返回值为常量 ++返回值 非法 不能通过编译

44.count_ones是计算非零整数x的二进制表示下,有多少个bit是1.例如:10 = (1010)2,则返回2,填写空行。
int count_ones(unsigned int x)

{

assert(x > 0);  

int ones = 1;

while (______x = x_&____________________)ones++;

return ones;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值