关于C的一些小知识点

1  CPU对寄存器的读写一般是按照数据宽度一起进行的,也就是32bit读入,32bit写入,也就是假设我们只想修改其中某一个位的话,也是整体读取,修改特定位,然后整体写入

2 寄存器特定位清零用&  var1 = 0xAAAAAAA若想将8到15位清零,可以使用 var1 &= 0xFFFF00FF

3 特定位置1用或 |  var1 = 0xAAAA00AA置1  var1 |= 0x0000FF00

4 寄存器特定位取反 ^ 

5 使用宏定义来完成位运算 将该位和1进行或操作  #define SET_BIT_N(x,n) ((x)|((n)-1))

6 使用宏复位  将该位和0与,其它位和1与  #define CLEAR_BIT_N(x,n) ((x)&~((n)-1))

7 所谓的段错误就是地址错误,一般是指针指向的地址不存在或者写受到限制导致的

8 const一旦定义不能修改

9 数组传参,传的是数组元素的首地址

10 #define只是简单的宏替换,在预处理的时候进行处理  typedef是重定义 在编译时进行处理

11 strlen以\0作为标记区分,但统计不包括 \0

12 常量也称为字面量,没有对应的存储单元

13 typedef本身并不产生新的变量类型,而是给现有变量起一个别名,类型本身并不占用内存,而变量是这个磨具的实例

14 Linux命令行默认缓冲,直到遇到\n  \r\n \r或者退出时才会输出,所以,调试时最好加上\n以免误判错误位置

15 scanf不会接收最后的\n 等下次scanf接收时,却会收到它,可能导致并没有拿到我们想要的数据,注意下这点

16 内存管理方式:栈(stack),堆(heap),数据区(.data和.bss区)和常量区(.ro.data)

17 栈内存管理的特点:

        1)运行时自动分配,运行结束自动回收

        2)可以反复使用

        3)脏内存,它可以反复使用,每次使用后并不会去清空内存,下次该空间被再次分配时上次使用的值还在

        4)临时性,函数不能反悔指针变量,因为程序运行结束之后该空间就会被释放

18 堆内存的特点:

1)空间较大

2)要手动申请和释放

3)脏内存,在使用完也不会清除数据

4)在malloc后和free前可以访问,malloc前和free后不可再访问,否则会造成不可预知的错误

  注:若分配的内存未手动释放,这块空间会一直被占用,只有整个程序结束时才会被释放

     malloc返回的是viod *型的指针,它表示万能指针,申请失败返回NULL

          malloc的一些细节表现:

          malloc(0)这么操作是没有意义的,假设真的这么操作,它的返回值是不确定的

          malloc(4)GC中的malloc是以16B为单位进行空间分配的,若指定空间小于16B,会分配16B


19 (.text)代码段:存放代码,程序的各种函数指令就存放在这里

   (.data)数据段:也称数据区 静态数据区  静态区,程序中的静态变量空间开辟于此

   .bss段:又称ZI(Zero Initial)段,所有的未初始化的静态变量存放在这里,自动把他们初始化为0

   .data .bss无本质差别,只是data用来存放显式初始化为非0的数据

bss用来存放显式初始化为0或者未初始化的数据

20 C中Const的试下有两种:

   1 存放在代码段,(代码段只读),来达到不能修改,单片机常这么做

   2 让编译器帮忙实现,编译器发现const修饰的变量试图被修改时会提示错误,本质是和普通变量一样的,GCC是这么做的


21 C中字符串的本质是指向字符存放地址的指针

   对于char *p = "linux"来说 p是指针变量,占用4或者8个字节  Linux存储于代码段,占用6个字节


22  sizeof得到的是类型的占用字节大小,在编译阶段就可以确定大小

    strlen得到的是字符串的长度


23 #prama pack(n) 告诉编译器,我们希望以几个字节对齐

24 结构体是多个独立元素(地址空间)打包在一起,union是一个元素(地址空间)的不同解析方式

  union的sizeof检测到的值是各个元素占用空间最大的那个元素的大小,不存在内存对齐,因为只有一个元素

  struct的sizeof检测到的是所有元素占用内存的总和,要考虑内存对齐


25 GCC中一些常见的文件扩展名

.c C语言源代码

.a 目标文件构成的静态库文件

.h 头文件

.i 经过预处理的C源码文件

.ii 预处理后的C++源文件

.m  Object-C 源文件

.o 编译后的目标文件

.out 连接器生成的可执行文件

.s 汇编源文件,不再进行预处理,不可包含预处理指令

.S 汇编源文件,还会进行预处理,可以包含预处理指令


26 编译链接的四个步骤:

   预处理 gcc -E *.c -o *.i

   编译   gcc -S *.i -o *.s

   汇编   gcc -c *.s -o *.o

   链接   gcc *.o -o *.out

17 #include <> 会在系统目录中查找库文件

   #include "" 会现在用户目录中查找

18 静态链接库就是将自己的库文件只编译不链接形成的.o目标文件,用ar工具归档成.a文件,使用时,会将库中的文件直接复制到使用它的文件中,若有多个文件include,就会复制多份到内存中,造成内存浪费

静态链接库不是将库文件直接复制到可执行程序,只是做一个链接标记,当程序需要时,加载到内存中,其它程序也需要时直接使用,在内存中只有一份

19 制作静态链接库   

  
  
  1. //demo.h
  2. void func1(void);
  3. int func2(int a,int b);
   
   
  1. //demo.c
  2. #include <stdio.h>
  3. void func1(){
  4.  printf("func1 in demo.c\n");
  5. }
  6. int func2(int a,int b){
  7.  printf("func2 in demo.c\n");
  8.  return a + b;
  9.  
  10. }
    
    
  1. //test.c
  2. #include <stdio.h>
  3. #include "demo.h"
  4. int main(){
  5.  func1();
  6.  int a = func2(4,5);
  7.  printf("a = %d\n",a);
  8.  return 0;
  9. }

制作静态库:

gcc demo.c -o demo -c 

ar -rc libdemo.a demo

1)使用命令gcc test.c -o test 会报错

clang: error: linker command failed with exit code 1 (use -v to see invocation)

原因是没有找到库函数demo.a

2)使用命令 gcc test.c -o test -ldemo

ld: library not found for -ldemo

clang: error: linker command failed with exit code 1 (use -v to see invocation)

原因是默认库文件查找路径为用户动态库的文件夹

3)gcc test.c -o test -ldemo -L.

可以正确执行,-L指定动态库的查找路径  .表示当前路径

20 制作动态链接库

   gcc -c demo.c -o demo -fPIC

   gcc -o libdemo.so demo -shared

1)使用命令gcc test.c -o test 会报错,同上静态库的错误信息

2)使用命令 gcc test.c -o test -ldemo同上

3)gcc test.c -o test -ldemo -L. 可以


21 1)register关键字很少用,使用时,系统会尽量把它分配到寄存器,效率会很高

     但它没有内存地址,不能使用&符号,而且不能保证每次都分配到寄存器,只能尽量

     变量的长度应小于寄存器的长度

22 在C中若变量从定义到使用始终未赋值,则在编译和运行虽然可以通过,却会得到意想不到的结果

    





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值