近期嵌软线下笔试题记录

1、以下代码的输出结果是?

#include <stdio.h>
#include <string.h>


int main()
{
    int a,b,c,d;
    a = 10;
    b = a++;              //a先赋值给b,然后自增1
    c = ++a;              //a自增1后赋值给c
    d = 10*a++;           //先进行运算然后a自增1
    printf("b,c,d:%d,%d,%d\n",b,c,d);//10 12 120
    printf("a:%d\n",a);//13


    system("pause");
}

b,c,d:10,12,120
a:13

主要考察知识:前置++,后置++,运算符优先级

2、以下代码有什么问题?

#include <stdio.h>
#include <string.h>

int main()
{

    char a;
    char *str = &a;
    strcpy(str,"hello");
    printf(str);


    system("pause");
}

导致内存访问错误,因为 char 变量无法容纳整个字符串 "hello",可用数组实现拷贝。

3、请写出以下代码的输出内容:

#include <stdio.h>
#include <string.h>

int main()
{

    char *c[] = {"ENTER","NEW","POINT","FIRST"};
    char **cp[] = {c+3,c+2,c+1,c};
    char ***cpp = cp;
    printf("%s\n",**++cpp);
    printf("%s\n",*__*++cpp+3);
    printf("%s\n",*cpp[-2]+3);
    printf("%s\n",*cpp[-1][-1]+1);

    system("pause");
}

这道题个人觉得有问题,只知道第一个输出为POINT,笔试的时候也是想了很久,回来后也用vs和ubuntu手敲的一遍,都编译错误。不知有无大佬知道这道题什么意思?

考察知识点:指针数组,二级指针,三级指针

4、指出下面代码里存在的所有问题,修正后输出结果是?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* fun1(char* x){
    char y = 0;
    y = *x+1+*(x+2);
    return &y;
}
char* fun2(){
    static char a[8] = {0};
    strcpy(a,"a+b=");
    return a;

}


int main()
{
    char a[5] = {1,3,5,7,9};
    char *b = NULL,*str1,*str2;
    b = fun1(a);
    str1 = fun2();
    strcpy(str2,"hello word,");
    printf("%s%s%d",str2,str1,*b);

    system("pause");
}

存在的问题

  1. fun1 函数返回一个指向局部变量的指针。在 fun1 中,声明了一个字符变量 y,并尝试返回它的地址。但是,一旦 fun1 函数执行完毕,y 将会被销毁,因此返回的指针将指向无效的内存位置。你应该避免返回指向局部变量的指针。

  2. str2 是一个指针,但没有分配内存给它。在 main 函数中,你声明了 str2 但没有分配内存,然后尝试使用 strcpy 复制字符串到 str2,这会导致未定义的行为。你应该分配足够的内存给 str2,或者使用字符数组来存储字符串。

修改后的代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* fun1(char* x){
    static char y = 0;//用static来延长变量的生命周期
    y = *x+1+*(x+2);
    return &y;
}
char* fun2(){
    static char a[8] = {0};
    strcpy(a,"a+b=");
    return a;

}


int main()
{
    char a[5] = {1,3,5,7,9};
    char *b = NULL,*str1,*str2;
    //char *str1 = NULL;
    //char *str2 = NULL;
   
    b = fun1(a);
    str1 = fun2();
    str2 = malloc(12*sizeof(char));//为str2o动态分配内存
    strcpy(str2,"hello word,");
    printf("%s%s%d",str2,str1,*b);
    free(str2);
    system("pause");
}

总结起来,str1 不需要额外的内存分配,因为它返回的是指向静态数组的指针,而静态数组在整个程序的生命周期内都存在。而 str2 需要内存分配,因为你希望将字符串复制到一个动态分配的内存块中,这需要通过 malloc 或类似的函数来显式地分配内存。

还有指针定义的时候要初始化,虽然上面代码str1和str2没有初始化也可以正常运行,但是还是希望大家进行初始化,否则可能出现野指针的情况。

5、实现memcpy函数,函数功能是将源地址内容拷贝到目的地址,并返回目的地址。

void *memcpy(void *dest,void *src,size_t n);

void *memcpy(void *dest,void *src,size_t n)
{
    char *d =(char *)dest;
    const char* s =(const char *)src;
    for(size_t i=0;i<n;i++){
        d[i] = s[i];//逐个字节进行拷贝
    }
    return dest;
}

6、实现memmove函数,与memcpy的区别是需要保证源地址目的地址存在重叠时仍然能够得到预期效果

void* memmove(void* dest,const void *src,size_t n);

void* my_memcpy(void* dest, const void* src, size_t n) {
    if (dest == NULL || src == NULL) {
        return NULL; // 处理空指针情况
    }

    unsigned char* d = (unsigned char*)dest;
    const unsigned char* s = (const unsigned char*)src;

    // 如果源地址和目标地址有重叠,从后往前拷贝
    if (d > s && d < s + n) {
        d += n - 1;
        s += n - 1;
        for (size_t i = 0; i < n; i++) {
            d[i] = s[i];
        }
    } else {
        for (size_t i = 0; i < n; i++) {
            d[i] = s[i];
        }
    }

    return dest;
}

7、实现一个函数,该函数的功能是判断当前机器是大端字节序还是小端字节序

int check_endianness() {
    unsigned int num = 1;
    unsigned char *ptr = (unsigned char *)&num;

    if (*ptr == 1) {
        return 1; // 小端字节序
    } else {
        return 0; // 大端字节序
    }
}

8、内存溢出一般是什么原因导致的?段错误是什么原因导致?

内存溢出是指程序试图分配的内存超过了系统或应用程序能够提供的可用内存。这可能导致程序崩溃、异常终止或不稳定的行为。内存溢出通常出现在以下几种情况:

动态内存分配不足   数据结构过大  资源泄漏

段错误(Segmentation Fault,通常缩写为 SegFault)是一种操作系统产生的错误信号,指示程序访问了其内存范围之外的区域。通常是由以下几种情况引起的:

访问无效指针 栈溢出 访问受保护的内存区域

9、全局变量和局部变量在内存分配的区别?

总之,全局变量在整个程序生命周期内存在,分配在静态数据区或全局数据区,而局部变量在函数调用期间存在,分配在栈内存中。选择何时使用全局变量或局部变量需要根据变量的作用范围、生命周期和内存管理等因素进行权衡。

10、gcc的编译过程

预处理-----编译-----汇编------链接

11、什么是互斥锁?什么是信号量?产生死锁的原因?

互斥锁(Mutex) 是一种同步机制,用于控制多个线程对共享资源的访问。它确保在任何给定时刻只有一个线程可以访问被保护的共享资源,从而防止多个线程同时修改同一数据而导致的竞态条件。

互斥锁的基本操作是两个:上锁(Lock)解锁(Unlock)。当一个线程尝试上锁时,如果锁没有被其他线程占用,那么它可以获取锁并访问资源,否则它会被阻塞,直到锁被释放。解锁操作会释放锁,允许其他等待的线程获得锁。

信号量(Semaphore) 也是一种用于多线程同步的机制,但它可以管理多个线程对资源的访问。信号量维护一个计数器,表示可用资源的数量。当线程想要使用资源时,它会尝试获取信号量,如果计数器大于零,线程就可以继续执行,同时计数器减少;如果计数器为零,线程会被阻塞,直到有其他线程释放资源并增加计数器。

死锁 是一种多线程同步问题,指的是多个线程相互等待彼此持有的资源,导致所有线程都无法继续执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值