001 c语言查漏补缺1

  1. uint8_t、uint16_t来源问题:
    这些类型的来源:这些数据类型中都带有_t, _t 表示这些数据类型是通过typedef定义的,而不是新的数据类型。也就是说,它们其实是我们已知的类型的别名。

  1. #和##区别
    #将右边的参数做整体的字符串替换。
    ##将左右两边的参数做整体的字符串拼接替换。
#include <stdio.h>
#define f(a,b) a##b
#define g(a)  #a
#define h(a) g(a)
int main()
{
	 printf("%s/n",h(f(1,2)));
	 printf("%s/n",g(f(1,2)));
	 return 0;
}

  1. C语言中嵌入汇编:
    ATPCS规则(ARM/Thumb Procedure Call Standard):规定子程序间调用规则,寄存器调用规则,堆栈使用规则,参数传递规则
    汇编代码简洁,直接内嵌汇编,否则要将汇编程序以文件形式加入项目中,按照ATPCS规则与C程序相互调用与访问
  • 嵌入的形式
    • Linux gcc支持
__asm__("instruction"
...
"instruction");
* ADS中支持
 __asm(instruction
    ...
    instruction);
* ARM C++支持
asm("instruction[;instruction]");

  1. 预编译
    ① 类型1
#if defined(macro1) || (!defined(macro2) && defined(macro3))
...
#else
...
#endif

② 类型2

#define SOMETHING 1
#if SOMETHING == 1
...
#else
...
#endif

③ 类型3

	#define SOMETHING 1
	#if defined (SOMETHONG)
	....
	#else
	#endif

④ 类型4

#define SOMETHING 1

#if SOMETHING == 1
...
#elif SOMETHING == 2
...
#endif

  1. volatile要点
    使用了volatile的变量在使用优化语句是for()循环并没有得到优化,因为for()循环执行的是一个空操作,那么通常情况下使用了优化语句使得这个for()循环被优化掉,根本就不执行。就好比编译器在编译的过程中将i的值设置为大于或者等于10000000的一个数,使得for()循环语句不会执行。但是由于我们使用了volatile,使得编译器就不会自作主张的去动我们的i值,所以循环体得到了执行。举这个例子的原因是要让读者牢记,如果我们定义了volatile变量,那么它就不会被编译器所优化。
    当然volatile还有那些值得注意的地方呢?由于访问寄存器的速度要快过直接访问内存的速度,所以编译器一般都会作减少对于内存的访问,但是如果将变量加上volatile修饰,则编译器保证对此变量的读写操作都不会被优化。

  1. #pragma关键字
    在所有的预处理指令中,#pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。

  1. 结构体字节大小问题
  • 原则1:数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,
    后面每个数据成员存储的起始位置要从该成员(自身)大小的整数倍开始(如int在32位机为4字节,则要从4的整数倍地址开始存储)。

  • 原则2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。
    (struct a里存有struct b,b里有char,int,double等元素,那b应该从8的整数倍开始存储。)

  • 原则3:计算工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

struct A{
    int a;
    double b;
    float c;};

struct B{
    char e[2];
    int f;
    double g;
    short h;
    struct A i;};

sizeof(A) = 24; int为4,double为8,float为4,总长为8的倍数,补齐,所以整个A为24。
为什么 sizeof(A)不是 16,原则1写明后面每个数据成员存储的起始位置要从该成员(自身)大小的整数倍开始(如int在32位机为4字节,则要从4的整数倍地址开始存储)。即struct A里面的double b要从8的倍数开始,因为前面是4个字节,所有要补够四个,使double b从地址8开始,

sizeof(B) = 48;

B的内存布局:11* *(e), 1111(f), 11111111(g), 11* *****(h),1111****(i), 11111111(i), 1111****(i)

i其实就是A的内存布局。i的起始位置要为8的倍数,所以h后面要补齐。把B的内存布局弄清楚,有关结构体的对齐方式基本就算掌握了。


  1. 字符串常量和字符变量区别
    字符‘A’只占用1个字符,字符串常量“A”占两个字符。
    因为创建字符串常量时候,系统自动在字符串后加上一个NULL。

  1. typedef使用
  • 定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。
char* pa,pb;//pa是指针变量,pb是字符变量
typedef char* PCHAR;
PCHAR paa,pbb;//paa是指针变量,pbb是指针变量
  • 掩饰复合类型
char line[81];
char text[81];
typedef char line[81];
  • 定义一个 typedef,每当要用到相同类型和大小的数组时
line text,secondline;//text和secondline都是81个元素的数组
getline(text);
typedef char * pstr;
int mystrcmp(pstr,pstr);//标准库函数strcmp(const char*,const char*)
int mystrcmp(const pstr,const pstr);//当我们这样使用时,GNU的gcc和g++编译器会报错,把const pstr解释为 char * const,并不是我们想象中的解释为 const char *,改正方法如下
typedef const char* pstr;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值