B.Linux

灵魂构造师

导航

嵌入式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\n*p2 = %s\n*p3 = %s\n",p1,p2,p3);
    p1 = b;
    p2 = b;
    *p3 = a[1];
    //p3 = b;
        printf("*p1 = %s\n*p2 = %s\n*p3 = %s\n",p1,p2,p3);

    return 0;
    
}

sizeof和strlen

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

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

  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\n",sizeof(p));
    printf("sizeof(*p)= %d\n",sizeof(*p));
    printf("*(p+1)= %c\n",*(p+1));
    printf("strlen(p)= %d\n\n",strlen(p));
    printf("sizeof(str)= %d\n",sizeof(str));
    printf("sizeof(str[0])= %d\n",sizeof(str[0]));
    printf("strlen(str)= %d\n",strlen(str));
        printf("%p\n",p);
            printf("%p\n",&str[0]);
                printf("%p\n",str);
                    printf("%p\n",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\n",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\n",**p);
    printf("a[0][0] = %d\n",*(*p+1));
    printf("a[1][3] = %d\n",*(*(p+1)+3));
    printf("=============\n");
    //a[i][j] <==>*(*(p+i)+j)
    printf("a[0][0] = %d\n",*p1);
    printf("a[0][1] = %d\n",*(p1+1));
    printf("a[1][3] = %d\n",*(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\n",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\n",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\n",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\n",sizeof(s1));
    return 0; 
}
sizeof(s1) = 28

--------------------------------
Process exited after 0.02381 seconds with return value 0
请按任意键继续. . .
运行结果

 

 

 

 

 

 

 

posted on 2019-09-11 13:28  B.Linux  阅读(855)  评论(0编辑  收藏  举报