char buf[8*1024];
8K的字节,看上去没有问题,但是编译器对局部变量有两种优化的方法,第一种:对于简单的数据类型的变量比如(char ,int,short或者指变量等)编译器会尽可能的采用CPU内部通用寄存器,因为内部通用寄存器的访问速度远远高于外部存储器的访问速度;第二种方式是对于那些那些没有办法使用寄存器 表示的变量或者数组/结构体等变量采用当前堆栈空间存储,,显然8K在嵌入式程序中和可能耗尽堆栈的资源。
深刻的理解存储器,每一个存储器都有两个属性:以上存储器里面存储的内容;而是存储器的地址。
嵌入式开发的一个重要的特点就是交叉编译,也就是开发工具运行环境和被调试的程序不是运行在同一个硬件平台(处理器上)。
变量的存储类型☞存储变量值的存储类型,变量存储类型决定了变量何时创建、何时销毁以及其值能够保存多久,在C语言中的变量能够存放3个不同的地方:普通内存、运行时的堆栈、CPU内部的通用寄存器,,堆栈当然也是内存,但是相对于简单的内存来说堆栈变化更加的频繁,堆栈往往是用来存放暂存数据的。
变量的存储类型首先取决于它的声明位置,凡是在函数外声明的变量都是全局变量(默认情况下全局变量的作用域仅限于声明该变量的C文件中,如果希望在该C文件之外能够访问这个变量,程序员就需要在引用该变量的C文件之中进行外部extern进行声明),编译器在编译的过程中将全局变量映射到普通内存之中,在程序的整个执行期间该变量始终占用编译器为它分配的内存空间,它始终保持原来的值直到对这个变量进行赋值操作或者程序结束,所以有时我们也称全局变量为静态的。
static关键字可能是C语言中较多义的一个关键字,该关键字的具体含义取决于该关键字的不同的上下文,static关键字的三个不同的用途:
1.如果static对函数内部的局部变量声明时,static关键字的作用是改变局部变量的存储类型,从自动变量改为静态变量,也就是说这个局部变量不在存储在堆栈或者寄存器中,而是编译的时候由编译器分配一个静态的地址空间,但是这个变量的作用域不受影响,依然仅局限于声明它的函数内部才能够访问,需要说明的是一旦函数内部的局部变量被声明为static,这个函数就有可能不得重入;
2.如果static关键字被用于函数的定义的时候,这个函数就只能在定义的C文件之中使用,该C文件之外的代码将无法调用这个函数;
3.如果使用static对全局变量进行声明时,static关键字是的作用,类似于声明函数的情况,这个全局变量的作用域将局限在声明该变量的C文件内部,这个C文件之外的代码将无法访问这个变量(事实上采用指针的方式能够访问,但是既然声明成static的类型为什么要违背当初声明变量的初衷呢)。
struct关键字
面对一个C程序的时候,只看其中struct的使用情况我们就可以对其编写者的编程经验进行评估,从一定的程度上来说会不会使用struct、怎样使用struct是区别一个开发人员是否具备丰富开发经验的标志。
结构是有若干的(可不同类型的)数据项组合成符合数据对象,这些数据称为结构的成分或成员。
(1)牛逼的位域
有些信息在存储时,并不需要占用一个完整的字节,而只需占一个或几个二进制位。例如在存放一个开关量时,只有0和1两种状态,用一个二进制位即可。为了节省存储空间并使处理简便,C语言又提供了一种数据结构,称为”位域”或者”位段”。所谓”位域”是把一个字节中的二进制位划分为几个不同的区域,并说明每个区域的的位数。每个域有一个域名,允许在程序中按照域名进行操作。这样就可以将几个不同的对象用一个字节的二进制进行表示。。位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:
struct 位域结构名
{位域列表};
例如:
struct pack{
unsigned s:2;
unsigned b:8;
unsigned c:6;
}pk1,pk2;
由于位域不允许跨两个字节,因此位域的长度不能大于1字节长度,也就是说不能超过8位二进制位。
结构体内部的成员的对齐
在计算结构体长度时(尤其使用sizeof),需要注意根据不同的编译器和处理器,结构体内部的成员有不同的对其方式,这回引起结构体长度的不确定性。
结构体的某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获取,这个宏在stddef.h中定义如下:
#define offsetof(s,m) (size_t)&(((s * )0)->m)
大小端模式:
#include
void Get_Cont(void);
typedef unsigned char BYTE;
int main() {
unsigned int num,*p;
p = #
*(BYTE *)p = 0xff;
Get_Cont();
if(num == 0xff)
{
printf("The endian of cpu is little\n");
goto massge;
}
else
{
printf("The endian of cpu is big\n");
}
printf("Hello, World!\n");
massge:
printf("The endian of cpu is little\n");
return 0;
}
void Get_Cont(void)
{
printf("Get_Count!\n");
}
输出
Get_Count!
The endian of cpu is little
The endian of cpu is little
枚举是一种用于定义一组常量的机制,以这种方式定义的常量一般称为枚举常量,,一个枚举说明不但引入一组常量名,同事还为每一组常量确定了一组整数值,在默认的情况下其第一个常量自动的赋值0,随后的常量值顺序的递增。
(1)赋值的枚举常量,与给变量赋值一样,如果给一个枚举常量赋值,跟随其后的没有指定值的枚举常量也将跟着顺序递增取值,直到下一个有指定值的常量为止。
const关键字,ANSI中允许程序员利用const关键字声明一个变量是“只读”的。
const int a;
int const a;
//含义是一样的,都是声明整数变量a是只读的,可以根据自己好理解的形式进行编写;
const int *a;
//声明一个指向整数的指针变量a,这个指针的值是可以改变的,但是这个指针所指向的数值(*a)是不可以改变的;
int * const a;
//声明一个指向整数的指针变量a,这个指针的值是只读的,但是所指向整数数值(*a)是可以改变的;
int const * const a;
//声明一个指针变量a,不管这个指针变量的值还是指针变量所指向的整数值都是只读的,是不可改变的;
sizeof是一个C语言的关键字,许多程序员以为sizeof是一个函数,而实际上它是一个关键字,同时也是一个操作符sizeof关键字的作用就是返回一个对象或者类型所占的内存字节数
sizeof中看指针与数组的区别
char * ss = "0123456789";
sizeof(ss); //结果是4,ss是一个指向字符串常量的字符指针
sizeof(*ss); //结果是1,*ss是第一个字符
char s[] = "0123456789";
sizeof(ss); //结果是11,计算到‘\0’的位置,因此是10+1;
sizeof(*ss);//结果1,*ss是第一个字符
char ss[100] = "0123456789";
sizeof(ss); //结果是100,表示内存的大小是100*1
strlen(ss); //结果是10,strlen是计算到'\0'之前的数值;
int ss[100] = "0123456789";
sizeof(ss); //结果是400,ss表示在内存中的大小为100*4
strlen(ss); //错误,strlen的参数只能是char *且必须是以'\0'结尾
volatile关键字
一个定义为volatile的变量可能会被意想不到的改变,这样编译器就不会假设这个变量的值了。精确的说就是,优化器在使用到这个变量时必须每次都小心的重新的读取这个变量的数值,而不是使用保存在寄存器里面的备份。