坤之路 C基础(二)

坤坤防伪标签!!!!!!!!!!

文章收录到专栏中,便于大家学习

1.普通函数与宏函数的区别

1.编译时机:普通函数在编译时被编译器处理,函数调用会被替换为对函数的实际调用。宏函数在预处理阶段被处理,宏会在代码中被简单地展开,而不是被调用。

2.参数处理:普通函数的参数会被求值一次,且类型会被检查。宏函数的参数在展开时直接替换到宏定义中,不会进行类型检查,可能导致意外的行为。

3.代码大小:普通函数会生成独立的函数代码,增加了代码段的大小。宏函数在展开时直接将代码插入到调用点,避免了函数调用的开销,但可能会导致代码膨胀。

4.调试:普通函数有明确的函数调用栈,方便调试。宏函数在展开后,调试时可能会出现调试信息与源代码不匹配的情况。

5.作用域:普通函数有自己的作用域,不会影响其他代码。宏函数在展开时直接替换,可能会对代码的作用域造成影响。

2.C语言的基本类型有哪些(32位系统),占用字节空间数(要熟练)

char

1

short int

2

int/long int

4

char * /int * /任何的指针

4

float

4

double

8

3.头文件#ifndef/#define/#endif的作用

  • #ifndef:用于判断当前头文件是否已经被包含。
  • 如果该宏之前没有被定义过,则继续编译下面的代码。
  • 如果该宏之前已被定义过,则跳过下面的代码,直接到 #endif。
  • #define:用于定义一个宏。
  • 通过定义一个特定的宏名称,例如MY_HEADER_H表示头文件已被包含。
    • #endif:用于结束 #ifndef / #define / #endif 块。
    • 标记了头文件的结束位置。

    通过使用这种组合,可以防止同一个头文件被多次包含,以避免重复定义和编译错误。

    举例:

    #ifndef MYHEADER_H     // 如果 MYHEADER_H 还没有被定义
    #define MYHEADER_H     // 定义 MYHEADER_H
    
    void sayHello();       // 函数声明
    
    const int MAX_VALUE = 100;  // 常量定义
    
    #endif               // 结束条件编译
    
    上述是一般的使用模板
    

    4.如何判断大小端?

    #include <stdio.h>
    
    int check_endianness() {
        unsigned int num = 1;
        char *ptr = (char *)#
        
        if (*ptr) {
            return 1; // 小端序
        } else {
            return 0; // 大端序
        }
    }
    
    int main() {
        if (check_endianness()) {
            printf("This system is little-endian.\n");
        } else {
            printf("This system is big-endian.\n");
        }
    
        return 0;
    }
    
    

    在这段代码中,我们创建了一个无符号整数num并将其地址转换为指向字符的指针ptr。由于内存中存储数据的方式取决于系统的字节序,我们可以通过检查该指针指向的第一个字节来判断系统的字节序。如果第一个字节存储的是1,则说明系统是小端序;如果第一个字节存储的是0,则说明系统是大端序。

    5.内存泄漏和内存溢出是什么?

    (1)内存溢出:指程序申请内存时,没有足够的内存供申请者使用。或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错Out Of Memory,即所谓的内存溢出。

    (2)内存泄漏:是指程序在申请内存后,无法释放已申请的内存空间。一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

    6. strcpy和memcpy区别

    1.复制的内容不同。

    • strcpy只能复制字符串,
    • memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。

    2.复制的方法不同。

    • strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,如果空间不够,就会引起踩内存。
    • memcpy则是根据其第3个参数决定复制的长度。

    3.用途不同。

    • 通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy,由于字符串是以“\0”结尾的,所以对于在数据中包含“\0”的数据只能用memcpy。

    7.sizeof与strlen的区别

    sizeof:

    • 用于获取数据类型或变量的字节大小。
    • 可以接受多种参数,包括数据类型、变量名、数组名等。
    • 返回的是整个数据类型或变量占用的内存空间大小。

    strlen:

    • 用于获取以’\0’结尾的字符串的实际长度。
    • 在运行时计算,需要遍历字符串的内容来确定长度。
    • 返回的是字符串中的字符个数,不包括字符串结束符’\0’。

    举例:

    char str[] = "Hello";
    size_t size_str = sizeof(str);
    size_t length_str = strlen(str);
    // size_str 的值为 6,因为包括字符串 "Hello" 的 5 个字符和结尾的 '\0',共 6 个字节
    // length_str 的值为 5,因为字符串 "Hello" 有 5 个字符,不包括结尾的 '\0'
    
    

    注意事项:

    • sizeof返回的是静态的大小,而strlen返回的是实际的字符串长度。
    • 在使用strlen时要确保操作的对象是以’\0’结尾的字符串,否则可能出现不确定的结果。
    • sizeof可以用于任何数据类型或变量,而strlen只适用于字符串。

      8.结构体和共用体的区别:

    结构体(struct)和共用体(union)是在C和C++等编程语言中用来组织和存储数据的重要概念,它们之间有几个关键的区别:

    1.结构体(struct):

    • 结构体是一种用户自定义的数据类型,可以包含多个不同类型的成员变量。
    • 结构体的各个成员在内存中是按照定义的顺序依次存储的,每个成员有自己的内存空间。
    • 结构体的大小等于其所有成员变量大小之和,可能会有内存对齐的问题。
    • 结构体的各个成员可以同时被访问和操作。

    2.共用体(union):

    • 共用体是一种特殊的数据结构,所有成员共享同一块内存空间。
    • 共用体的大小等于其最大成员的大小,因为共用体中只有一个成员可以被同时使用。
    • 当一个共用体的成员被赋值后,其他成员的值会被覆盖,因为它们共享同一块内存空间。
    • 共用体通常用于节省内存空间,或者在需要在不同类型的数据之间进行转换时使用。

    9.一个指针可以是volatile吗

    一个指针可以被声明为volatile。在C和C++中,volatile是一个关键字,用于告诉编译器不要对声明为volatile的变量进行优化,因为这些变量的值可能在程序的控制之外被改变。

    当一个指针被声明为volatile时,意味着指针所指向的数据是volatile的,即这些数据可能会在程序的执行过程中被外部因素改变,如硬件中断、多线程操作等。因此,编译器不应该对这些数据的读写进行优化,而应该每次都从内存中读取或写入数据。

    示例:

    volatile int *ptr; // 声明一个指向volatile int的指针
    
    int main() {
        int a = 10;
        ptr = &a;
    
        // 在程序的其他地方可能会改变a的值,编译器不能对ptr所指向的数据做优化
        // 因此,每次访问*ptr时都应该从内存中读取a的值
        int b = *ptr; // 从内存中读取a的值
    }
    
    

    10.常见变量定义以及解释:

    • int a; // 定义一个变量 a,类型为 int
    • int *ptr_a;// 定义一个指针 a,指向 int 类型的变量
    • int **ptr_ptr_a;// 定义一个指针 a,指向一个指向 int 类型的指针
    • int arr[10];// 定义一个数组 a,有 10 个元素,每个元素是 int 类型
    • int *ptr_arr[10];// 定义一个数组 a,有 10 个元素,每个元素是 int 类型的指针
    • int (*ptr_to_arr)[10];// 定义一个指针 a,指向一个数组,该数组有 10 个元素,每个元素是 int 类型
    • int (*ptr_to_func)(int);// 定义一个指针 a,指向一个参数是 int,返回值是 int 的函数
    • int (*arr_of_func[10])(int);// 定义一个数组 a,每个元素是一个指向参数是 int,返回值是 int 的函数指针

    11.说说下面表达式的区别

    1. const int* p;
    2. int* const p;
    4. int const *p;
    5. const int* const p;
    
    1. const int* p;  这表示指针 p 指向一个常量整数。这意味着你不能通过 p 修改所指向的整数的值,但是你可以改变 p 指向另一个整数。
    2. int* const p; 这表示 p 是一个指向整数的常量指针。这意味着你可以通过 p 修改所指向的整数的值,但是你不能改变 p 指向另一个整数。
    3. int const *p; 这和第一个声明 const int* p; 是等价的,表示指针 p 指向一个常量整数。
    4. const int* const p; 这表示 p 是一个指向常量整数的常量指针。这意味着你既不能通过 p 修改所指向的整数的值,也不能改变 p 指向另一个整数。

    #面经##牛客解忧铺##牛客在线求职答疑中心##简历被挂麻了,求建议##字节跳动工作体验#
    全部评论

    相关推荐

    11-09 14:46
    已编辑
    河海大学成人教育学院 C++
    时间一个小时,我和面试官都没开摄像头面试官是个声音好听的女孩,是公司的技术总负责人,说是主管面实际上全程在聊技术。对着项目问的,我的消息队列好像撞到她的枪口上了。我的序列化方式是什么?xml,json类似的文本格式和二进制格式的对比?我只回答了可读性和存储大小,常用的二进制序列化protobuf。如果让你自己设计二进制序列化怎么设计?我说就把每个字段大小读出来,内容写到buf里。追问如果长度是可变的怎么办?比如结构体里有个vector。-&amp;gt;反序列化不出来。怎么解决?分析一下proto文件改变了,会出现什么问题,怎么解决。(就是对不同版本的兼容性问题)了不了解protobuf是怎么解决的。介绍消息队列?关键的的数据?我的消息队列是推模式还是拉模式,我是拉模式如果让我实现推模式怎么实现,怎么设计消费方接口的统一。回答完这个问题我说,我了解到常用的消息队列只会实现一种模式,她说dds就是推拉都有,后来搜了一下这是汽车常用的中间价....果然撞枪口上了...我的消息队列如何解决读消息冲突的?讲了集群模式怎么做的。如果广播模式要求所有的消费者收到消息,怎么做,什么时候可以删除一个物理消息队列,怎么标记.....这块花了挺长时间,她也问不清我也讲不清哈哈哈被问的有点慌了一个线程的整个生命周期?什么情况下会被挂起?你觉得什么是好的cpp代码?我答了做好内存管理,用简单的方式实现功能,避免使用复杂语法和特性(她说这点特别好)...怎么做到代码复用和可扩展性?用设计模式追问你常用哪些。讲一下CAP原理,分别在什么场景下牺牲哪一个特性。你觉得自动驾驶应该首先保证哪个。你有没有觉得比较好的编程习惯?有没有觉得写的特别好的库?我说了ffmpeg。反问:剩下的时间就交给你来问我了(好可爱)我着急回去上班,就没有反问,好后悔十分钟后通知通过了
    查看18道真题和解析
    点赞 评论 收藏
    分享
    11-08 14:17
    已编辑
    门头沟学院 Java
    #一觉醒来,秋招难度下降一万倍……#&nbsp;一觉醒来,整个计算机专业的秋季招聘难度突然下降了一万倍。而这一切,似乎只有你没有察觉到。早上,你像往常一样起床,洗漱完毕后,打开电脑准备继续昨晚未完成的算法练习。就在这时,你的手机突然响个不停,微信朋友圈里充满了各种同学的感叹与庆祝:“你们听说了吗?今年的秋招变简单了!”“天呐,阿里出的题目我都会做了!”“我刚刚面试了腾讯,面试官竟然让我教他递归函数怎么写!”你看着这些信息,一头雾水,心想:“这帮家伙又在搞什么鬼?”你决定去学校图书馆看看情况是否真的如此不同寻常。路上,你遇到了几个平日里一起学习的同学,他们兴奋地向你展示他们的简历——那些曾经让无数计算机专业的学生头疼不已的项目经历,如今几乎每个人都轻松罗列了几页。到了图书馆,你惊讶地发现,所有正在学习编程的学生都显得异常轻松,甚至有几个学弟学妹正在互相教授C++的基础语法。你找了个安静的角落坐下,试图通过刷LeetCode来提升自己的竞争力,但很快你就发现,上面的题目对现在的求职者来说,已经变得太过基础,许多人都能在极短的时间内解决。下午,你参加了几家知名科技公司的线上宣讲会,发现面试官们的问题比以往简单得多,有的甚至只是询问一些基本的数据结构概念。更让你意外的是,在一次技术面试中,面试官竟然向你请教如何实现一个简单的链表反转。你按照平时的习惯轻松解答,面试官则露出一副如获至宝的表情,仿佛得到了什么珍贵的知识。随着一天的结束,你逐渐意识到,这个世界对于计算机专业学生的挑战确实发生了翻天覆地的变化。你不再是那个需要熬夜刷题、拼命学习才能跟上步伐的普通学生,而是成为了众多企业争抢的对象。原本难以企及的梦想岗位,现在对你来说几乎是触手可及。几天后,你收到了多家顶级科技公司的offer,每一家都提供了优厚的薪资待遇和广阔的发展空间。你的同班同学也开始纷纷收到心仪公司的邀请,整个学院的氛围变得前所未有的积极向上。然而,正当你沉浸在这一系列突如其来的幸运之中时,你突然感到一阵眩晕。当你再次睁开眼睛,发现自己仍然坐在熟悉的书桌前,面前的屏幕上是那道尚未解决的算法题,而手机依旧静静地躺在旁边,没有任何新的消息提醒。原来,这一切只是一场梦。
    点赞 评论 收藏
    分享
    2 3 评论
    分享
    牛客网
    牛客企业服务