• 嵌入式C语言面试必备


    const关键词与指针

    const意味着只读。修饰指针的三种形式:

    1.   int const *p 等价于const int *p       --------指针的指向(p)可改,但是指针指向的内容(*p)不可改;
    2.   int *const p                                    --------- a刚好与上面相反:(*p)可改,(p)不可改;
    3.   int const * const p等价于const int *const p   ---------(*p)不可改,(p)不可改;
    #include <stdio.h>
    #include <string.h>
    int main()
    {
        char a[]="Nice to see you!";
        char b[]="Second point!";
        char c[20];
        const char *p1 = a ;     // *p1只读 
        char const *p2 = a;      // *p2只读 
        char * const p3 = a;     //  p3只读 
        printf("*p1 = %s
    *p2 = %s
    *p3 = %s
    ",p1,p2,p3);
        p1 = b;
        p2 = b;
        *p3 = a[1];
        //p3 = b;
            printf("*p1 = %s
    *p2 = %s
    *p3 = %s
    ",p1,p2,p3);
    
        return 0;
        
    }

    sizeof和strlen

    1.     sizeof运算符用于获取括号()里面数据类型或者变量所占用的内存字节数;
    2.     strlen求的是空间中实际的字符的个数,不包括结束符''。

    一维数组中的几个关键符号的理解

    1. buf:两层含义:一是数组名,如:sizeof(buf);二是等价于&buf[0],表示数组第一个元素的首字节地址,是一个地址常量值
    2. buf[0]:第一个元素的空间,可读写
    3. &buf[0]:等价于buf,是一个地址常量。
    4. &buf:表示数组首地址,是一个地址常量。与buf值相等但含义完全不同。&buf+1加1加的是整个数组的空间大小;buf+1加的是数组中一个元素空间大小
    //代码运行环境:window7 64bit
    #include<stdio.h>
    #include<string.h>
    int main()
    {
        char str[] = " hello";
        char *p=str;
        printf("sizeof(p)= %d
    ",sizeof(p));
        printf("sizeof(*p)= %d
    ",sizeof(*p));
        printf("*(p+1)= %c
    ",*(p+1));
        printf("strlen(p)= %d
    
    ",strlen(p));
        printf("sizeof(str)= %d
    ",sizeof(str));
        printf("sizeof(str[0])= %d
    ",sizeof(str[0]));
        printf("strlen(str)= %d
    ",strlen(str));
            printf("%p
    ",p);
                printf("%p
    ",&str[0]);
                    printf("%p
    ",str);
                        printf("%p
    ",p+1);
        return 0;
    }
    sizeof(p)= 8
    sizeof(*p)= 1
    *(p+1)= h
    strlen(p)= 6
    
    sizeof(str)= 7
    sizeof(str[0])= 1
    strlen(str)= 6
    000000000022FE40
    000000000022FE40
    000000000022FE40
    000000000022FE41
    
    --------------------------------
    Process exited after 0.2643 seconds with return value 0
    请按任意键继续. . .
    运行结果

    函数指针:

     一个函数:int func(void)

    其函数指针为:int (*p)(void);

    定义一个函数指针指向strcpy函数,并验证函数指针定义是否匹配

    #include <stdio.h>
    #include <string.h>
    int main()
    {
        char a[20];
        char* (*p)(char *,const char *);
         p= strcpy; 
        p(a,"nice to see you!");
        printf("a[20] = %s
    ",a);
        return 0; 
    }
    a[20] = nice to see you!
    
    --------------------------------
    Process exited after 0.03327 seconds with return value 0
    请按任意键继续. . .
    运行结果

    typedef和#define宏的区别

    与typedef不同,#define是单纯的替换,替换发生在预编译阶段,可以把#define的每个参数当做一堆字母,#define只是简单的一堆字母用另一堆字母替换,词义的分析不在它的范围;

    格式:

    typedef char * tpchar;
    #define dpchar char *

    typedef行和原型行只差一个typedef,而#define语句两个参数与typedef顺序相反

    typedef char * tpchar;
    #define dpchar char *
    dpchar p1,p2;    // char *p1,p2;
    tpchar p1,p2;     // char *p1,*p2;

    typedef与struct

    通常结构体在使用时都是先定义结构体类型,再用结构体类型去定义变量(必须带上struct)

    struct node{
         int age;
         char name[10];
    };
    struct node n;

    但配合typedef使用时,不需要在定义结构体变量时添加struct

    typedef struct node{
         int age;
         char name[10];
    } Node;
    
    Node n;

    typedef与数组、函数指针

    普通定义:char t[80]

    运用typedef:

    typedef char line[80];
    line t;

    函数指针普通定义;int (*fp)(int,int)

    运用typedef:

    typedef int (*func_ptr)(int,int);
    func_ptr fp;

    typedef与const

    typedef int *PINT;  const PINT p2;相当于int *const p2, 等价于typedef int *PINT;PINT const p2;

    指针的指向的地址p2不可改变

    typedef const int *PINT;PINT p3;相当于 const int *p3

    指针指向的内容*p2不可改变

    注:

       typedef就是给类型取个别名,如上定义就是给一个函数指针类型取了个别名func_prt。

       typedef在语法上是一个存储类的关键字(如:auto,extern,static,register),而一个变量只能被一种存储类的关键字修饰。

     野指针:

     所谓野指针就是指针指向一个不确定的地址空间,或者地址空间确定,但引用空间的结果却不可预知。

    两个小例子:

    eg1:
    //指针p是一个局部变量,未初始化,没有后续赋值,所以p指向的内存空间不确定,结果未知。
      int main(void)
    {
       int *p;
       *p   = 10;
       return 0;
    }
    eg2:
    //p虽然指向了一个确定地址空间,但是这个空间是否存在,读写权限是否满足程序的访问要求,都未知,所以结果未知。
     int main(void)
    {
        int *p = 0x12345678;
        *p     =  10;
        return 0;
    }

    数组指针访问二维数组:

    #include <stdio.h>
    int main()
    {
        int  a[2][4] = {{4,5,6,7},{8,9,0,1}};
        int (*p)[4] = NULL;
        int *p1=NULL,*p2=NULL;
        p1 = a[0];
        p2 = a[1];
        p = a;
        printf("a[0][0] = %d
    ",**p);
        printf("a[0][0] = %d
    ",*(*p+1));
        printf("a[1][3] = %d
    ",*(*(p+1)+3));
        printf("=============
    ");
        //a[i][j] <==>*(*(p+i)+j)
        printf("a[0][0] = %d
    ",*p1);
        printf("a[0][1] = %d
    ",*(p1+1));
        printf("a[1][3] = %d
    ",*(p2+3));
        return 0; 
    }
    示例代码
    a[0][0] = 4
    a[0][0] = 5
    a[1][3] = 1
    =============
    a[0][0] = 4
    a[0][1] = 5
    a[1][3] = 1
    
    --------------------------------
    Process exited after 0.08917 seconds with return value 0
    请按任意键继续. . .
    运行结果

    对于二维数组a[2][4]而言:a等价于&a[0],a[0] 等价于&a[0][0],故a等价于&&a[0][0]。

    结构体字节对齐

    先介绍一个概念——偏移量,结构体中的偏移量就是结构体成员和结构体变量的地址之差,
    比如说第一个结构体成员的偏移量就是0,第二个结构成员的偏移量就是第一个结构体成员
    的大小,假如第一个成员的是int b;那么第二个结构体成员变量的偏移量就是4,
    计算结构体大小的规则:
    1.每一个成员的偏移量都必须是该成员的倍数。
    2.结构体的大小必须是该结构体字节数最大成员的倍数。

    手动对齐:

    #pragma用于告诉编译器,程序员希望自定义对齐方式。

    常用的手动设置字节对齐的命令:

    1、 #pragma pack(),这种就是设置为1字节对齐或者说是设置为不对齐或取消对齐

    2、#pragma pack(4),表示手动设置为4字节对齐

    使用方法:在需要自定义对齐方式的开头运用命令:#pragma pack(n) ,结尾运用命令:#pragma pack()

    GCC中也可以使用推荐的对齐指令:

    _attribute_((packed)):取消对齐

    _attribute_((aligned(n))) :n字节对齐

    #include <stdio.h>
    struct num{
        char a[10];
        double b;
        int c;
        char d;
    }s1; 
    int main()
    {
        printf("sizeof(s1) = %d
    ",sizeof(s1));
        return 0; 
    }
    sizeof(s1) = 32
    
    --------------------------------
    Process exited after 0.05793 seconds with return value 0
    请按任意键继续. . .
    运行结果
    #include <stdio.h>
    #pragma pack(1) 
    struct num{
        char a[10];
        double b;
        int c;
        char d;
    }s1; 
    #pragma pack()
    int main()
    {
        printf("sizeof(s1) = %d
    ",sizeof(s1));
        return 0; 
    }
    sizeof(s1) = 23
    
    --------------------------------
    Process exited after 0.02397 seconds with return value 0
    请按任意键继续. . .
    运行结果
    #include <stdio.h>
    #pragma pack(2) 
    struct num{
        char a[10];
        double b;
        int c;
        char d;
    }s1; 
    #pragma pack()
    int main()
    {
        printf("sizeof(s1) = %d
    ",sizeof(s1));
        return 0; 
    }
    sizeof(s1) = 24
    
    --------------------------------
    Process exited after 0.3388 seconds with return value 0
    请按任意键继续. . .
    运行结果
    #include <stdio.h>
    #pragma pack(4) 
    struct num{
        char a[10];
        double b;
        int c;
        char d;
    }s1; 
    #pragma pack()
    int main()
    {
        printf("sizeof(s1) = %d
    ",sizeof(s1));
        return 0; 
    }
    sizeof(s1) = 28
    
    --------------------------------
    Process exited after 0.02381 seconds with return value 0
    请按任意键继续. . .
    运行结果
     
  • 相关阅读:
    Java Object类及其常用方法
    Java 抽象类和抽象方法
    Java 多态
    Java 继承
    Java Scanner类
    正则表达_1
    「暑期集训day14」掠影
    「暑期集训day13」苦闷
    「暑期集训day12」苦楚
    「暑期集训day11」旧殤
  • 原文地址:https://www.cnblogs.com/embeded-linux/p/11505755.html
Copyright © 2020-2023  润新知