C语言中的一些小坑记录(sizeof,函数指针,长字符的值)

2018-12-28  本文已影响0人  zevolv

说在前面

好久都没有用过c了(之前用c++写过合数fft,算法而言没有遇到很多坑),好像以前学习的时候也没怎么学。某些知识点很容易遗忘,稍微写点东西记录一下。以下内容仅用于学习用途,不可以用作其他用途。



tips:所有思考题的答案都在文末


1 字符类型和数字
int a = '12'; // 默认256进制,且数字为ascii的值
/**有 ‘\’存在时有少许变化*/
int b = '\0' ;//后面跟0到2位8进制,之后全为256进制
int c = '\???' ; // \ 后面的?可以为8进制,第一位为0参照上一条,否则后面跟0到2位8进制,之后全为256进制
int e = '\x';//这种方式x后面跟0到2位16进制(与x连接的0最后一个有效,如\x000aa = \x0aa),最多两位(不含无效0),之后全为256进制

思考题 char a = '00'; a = ?;



2 sizeof 和 struct
  struct A{
    
    int a;
    char b[5];
    int c;
    short d;
  };
  
struct B{
    
    int a;
    char b[5];
    short d;
    int c;
  };

  sizeof(A) == sizeof(B) // false
//这里false的原因主要是内存字节对齐导致的,内存的字节对齐默认是结构体基础数据结构里面最大的为准。
//A 和 B 明明是一样的变量 但sizeof(A) = 20,sizeof(B) = 16,所以对齐采用相对良好的设计会节省很多内存。
// 具体对齐方式的话 按照结构体的顺序放入到内存,尽可能的保证内存不切片。如下所示(假设每个片段为4字节)
//      Mem                          A                             B
//1      0x1000                      a                              a
//2      0x1004                     b[0]~b[4]                 b[0]~b[4]
//3------0x1008                     b[5]                         b[5],d             
//4      0x100c                      c                                c
//5      0x1010                      d                                

//第三行的话,由于片段大小为4, 所以不能同时放下 b[5] 和c 但可以放下 b[5] 和 d
//记笔记,从内存地址取值的时候,如果把c切片成3字节放在第三行,剩下一个字节放在第四行,这样子对c的读取就会需要两次读取,会降低效率的

// 结构体含结构体的情况,计算最大对齐内存只需要计算基础类型

思考题

struct A{ char a; int b;double c ;int d ; };
struct B{ int a;short b;char c[8];struct A d; int e;unsigned int f; };
sizeof(B) = ?

3 函数指针
/**声明*/
int *(*p)();
void (*p)(void *,int);

思考题 描述一下p((void *) &q) 的执行过程

void q(void *);
void p(void *a){
   ((void (*)(void *)) a)((void *)&q);
};
void q(void *a){
    ((void (*)(void *)) a)((void *)&p);
};
4 const
  char * const p = "123456";
  char *n = (char*)malloc(10);
  strcpy(n,"123456");
  char const * q = n;
  const char * m = "123456";

  q++;//q  "23456\0"
  m++;//m  "23456\0"    
  p++;// err
  q[0] = '0';//err
  m = '0';//err
  p = '0';// p  "023456\0"
//const 修饰的不能改变,仅限修饰的对象

思考题 const char * a = "123456"; a[0] = '\0'; printf(a);

5 typedef

主要是用于方便,没啥好记录的

typedef char * charptr;
typedef void (*p)(void *,int);

//使用
charptr a = 0,b = 0;
void func(p a){
    if(a == NULL) return ;
    a(0,0);
}
6 string

strcpy ,memcpy,memmove,等使用不当会访问到非法内存(不是自己申请的空间)。

令人激动的答案

  1. '0' (不管大小端机器的都是0)
  2. 48 (仔细看注释就明白了)
  3. 题意可能有点蒙,也可能蒙得出来,对,这就是一个循环
  4. (a[0] = '\0' 就算没有const都会报错!)自己去执行看看,这个解释起来没意思了呀

结语,C语言总的来说还是不错的,轻便易使用,但是我好像好几年都没有接触过这些即使我学过。

有问题可以给我发邮件 yoghourtrain@gmail.com

上一篇 下一篇

猜你喜欢

热点阅读