C 面试题

C 面试题10.23

strlen 统计字符串中字符个数,不计算 \0

strcpy 复制字符串,会复制 \0

sizeof 关键字,会统计 \0

  1. char * const * ( *next )();

    函数指针的声明:**函数返回值类型 ( * 指针变量名称) (函数参数列表) **

    *next 是个指针变量

    (*next)() --next 是个函数指针 —— 指向函数的指针

    const *( *next)() --第一个 const * 代表 返回值 是 常量指针 类型

    char *const 常量指针类型—— 该函数指针的类型 该指针指向一个字符串。

    char * const * ( next )(); next是一个函数指针,该函数形参列表为空,返回值是双重指针 char * const ,即返回一个指向char型指针的常量指针(类似char

    是一个指向next()函数的指针,这个next()函数返回一个指针,这个指针是一个只读的指针,只读的指针指向一个字符指针。

  2. char * ( *c[10]) (int * *p);

    c[10]是一个数组。

    *c[10]是一个指针数组,存放10个 指针

    *( *c[10])(int * *p) 是一个函数指针的数组,函数有一个int **p形参,且返回值是指针。

    char * ( *c[10]) (int * * p); c是一个数组,该数组用于存放10个函数指针,该函数,有一个int * * 的形参,返回值是 char 类型 指针。

char *s = "AAA";        // 字符串常量
printf("%s",s);          //编译器接受字符串地址会自动输出字符串地址的内容,想要输出地址要强制转换成void*
s[0] = 'B';   		// *s = 'B';  效果相同,*s 指向字符串的第一位 ,修改指向的数据
printf("%s",s);

s = "BBB";      // 可执行 输出为 BBB,改变了 指针指向的位置

函数有问题(段错误,有段错误一定是指针操作有问题),第一个输出是 AAA ;第二个输出 段错误,第一次定义s字符串为常量,常量在代码的只读区域,无法修改
  1. 在一个绝对地址0x4002 0800 内写入数据整型值 0x3456

    // 将整形地址数值 转换为指针类型
    int *p;
    p = (unsigned int *)0x40020800;
    *p = 0x3456;
    
    #define  addr  (*(volatile unsigned int *)0x40020800)  // volatile 编译器不优化 
    addr = 0x3456;
    
  2. #define typedef 区别

    #define M(a,b) a*b
    printf("%d",M(5+1,6));        // 输出 5+1*6 = 11
    
    #define dps  int *         
    typedef int * tps;
    dps a,b;             // a 是 整型指针,b 是整形  相当于 int *a,b;
    tps c,d;             // 相当于 int *c,*d;
    
    1.定义格式不同
    
    2.原理不同
    #define  是预处理中的宏定义命令,只是简单的字符串替换,不做正确性检查
    typedef  是关键字,在编译处理时有类型检查功能
    
    3.作用域不同
    #define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,因此使用#define之后为了防止错误,要将其解除掉。但是typedef有自己的作用域。
    
  3. #include <stdio.h>
    char *get_str(void);
    
    int main(void)
    {
    	char *p = get_str();    // 该函数无返回值,p是空指针
        printf("%s",p);
        return 0;
    }
    
    char *get_str(void)            // str字符数组 是局部变量,局部变量存在栈空间内,当前函数执行完后,字符数组的地址将被释放(地址变为 无效地址),编译执行后产生段错误
    {
    	char str[] = {"ABCD"};     //1. 可以在前面加 static 将该str的地址申请在 静态存储区
    	return str;             // 2.可以将char str[] 改为 char *str, 字符串ABCD是常量,数组是变量,*str 指向常量地址,返回的 str 也是常量地址,该地址不会消失,       
    }
    
    
    返回值 是指针时,变量和指针分配在栈空间内,调用函数结束,就会释放掉里面的数据,因此虽然返回了一个指针,指针指向的数据却已经被系统销毁了,这就导致返回的指针指向不可预知的数据。
    // 函数内变量声明在栈内,返回时释放栈空间,该空间变为无效地址(返回的指针不会改变,指针所指的值会被是释放,即该数组内的值改变);变量若在静态区域,返回时该地址依然存在(返回的是静态区字符串常量的地址)。
    
  4. unsigned int a=6;
    int b = -20;
    a+b
    
    1.自动类型转化  无符号+ 有符号 时 有符号转换为无符号
    2.数字 以 补码形式保存          
    	正数 补码 = 源码   
    	6:0000 0000 0000 0000 0000 0000 0000 0110
       -20:原码: 1000 0000 0000 0000 0000 0000 0001 0100   第一位是正负标志位
            反码: 1111 1111 1111 1111 1111 1111 1110 1011   除第一位外取反
            补码 = 反码 +1 : 1111 1111 1111 1111 1111 1111 1110 1100
    
    a+b 补码相加 且结果为无符号数
    printf("a+b=%d",a+b);  // 结果输出 -14 ,因为 %d 将该数据以有符号的形式输出
    printf("a+b=%ud",a+b); // %ud 以无符号形式输出
    
  5. 大小端
    大端模式:低位 放在内存高地址中,高位放在低地址中
    小端模式:低位放在低地址中,高位放在高地址中           
    
  6. 取出当前系统下 无符号整形 的最大值最小值
    最小值为 0
    最大值为 ~0      不是 0xFFFF ,几个F 由系统多少位决定,不知道多少位时 0取反
    
  7. 逻辑与和运算与
    while(i<arrsize && arr[i] != x)  判断两个条件的逻辑值,全真为真
    while(i<arrsize &  arr[i] != x)  输出两个的计算值
    
    1.两个条件的结果 非1即0 则两个 符号作用相同
    
    2. x && y       x 为假时y不看
       x & y        y为任何值均需计算
    
  8. printf 函数的返回值
    一般直接调用 printf 输出显示字符,但它有返回值
    返回 输出打印的字符 的个数
    
  9. # 运算符——利用宏参数创建字符串
    
    #include <stdio.h>
    #define  square(x)  (printf(" "#x" square is %d\n ",(x) * (x)) )      // #x  被x的值替换  简单的字符串替换
    int main(void)
    {
    	square(2+4);    // 输出 2+4 square is 36
    	return 0;
    }             // 输出x 的平方
    
  10. ## 运算符的作用_预处理 符号粘合剂
    
    #include <stdio.h>
    #define   xname   x##n    // xn 不粘合 是两个符号,则x1是未定义的,n前 加 ## 则两个符号粘合成一个   
    int main(void)
    {
        // int x1=10;
    	int xname(1) = 10;
    	printf("%d",x1);
    	return 0;
    } 
    
  11. 结构体中 数组和指针
    代码改错:
    struct std
    {
    	unsigned int id;
    	char *name;          // 指针定义时一定要初始化, 应使用字符数组,预先开辟好空间
    	unsigned int age;    
    }per;
    
    int main(void)
    {
    	per.id = 0001;
    	strcpy(per.name,"stuname");  //
    	per.age = 20;
    	printf("%s\n",per.name);
    	return 0;
    }
    1.结构体中的指针,定义时需决定指向的地址或者定义为空,否则为野指针,可能指向不能访问的区域
    2.结构体中指针 占4个字节空间,只能存地址,主函数中拷贝字符串,空间不够
    
  12. 内存越界
    
    char *p1 = "ABCABC";
    char *p2 = (char *)malloc(strlen(p1));  // 开辟空间字节数
    strcpy(p2,p1);      // p1 拷贝到 p2
    
    p1末尾带‘\0’ ,strlen不计算 \0,所以字节数为6,开辟6个字节的空间,
    strcpy 时 p1 比 p2 多个 \0 ,当printf打印 p2时 函数一直打印到‘\0’,没有\0 则一直打印乱码
    
  13. 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  14. free() 和 delete 如何操作指向动态开辟内存的指针
    
    C中 开辟内存用malloc() , 释放内存用free()
    C++中 开辟用new 和 delete
    
    - malloc/free 是 函数,new/delete 是运算符
    - malloc 申请的空间不会初始化,new 可以初始化
    - malloc 返回值是 void*,使用时必须强转,new不需要,new后跟的就是数据类型
    - 申请自定义类型对象时,malloc 只会开辟空间,不会调用构造/析构函数,new / delete会 调用 构造/析构函数 
    - delete 指针时,先调用析构函数,再释放空间
    
    - free() 函数和delete,都只是把指针释放,指针变为野指针,并没有删除指针 
    - 指针释放之后为野指针,不可以再使用,会有麻烦
    - 指针释放之后最好设为空指针
    
  15. 字符串数组 和 指针 两种方式定义的字符串的区别
    
    char a[] = "abcd";		    
    char *b = "nmpq";          //字符串的地址是常量 , b 指向它 
    char *q = "xyz";
    
    a 是常量,是字符数组中第一个元素的 首地址,不允许修改
    b 和 q 都是指针变量,只存放一个地址,此地址是字符串的首地址,可以传值
    
  16. 哨兵思想
    
    在N个有编号的箱子内均放入一个数,查找某个数时:遍历N个箱子,比较数字是否相同
    哨兵:设立第N+1号箱子,在此箱内放入要找的数,则省去 判断箱子编号是否超过N的步骤
    

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  17. 一条 Linux 内
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值