关于C语言对内存方面的运用

关于C语言对内存方面的运用

===========

本来想做U3D开发的,却进入cocos-2dx公司,上手的项目全是C++代码编程的,到手一看就傻眼。。。。
算了,先一步步来吧,重新温习了C语言,因为以前接触过简单的C语言(四年前)和OC(两年没敲了),所以直接翻出C语言基础(百度搜索:菜鸟教程)准备温习温习凑合着看几眼把它捡起来,结果越看越欢喜,原因就在于,C语言里对内存的运用太牛叉了,

指针

说起C语言对内存的运用,就不得不提指针,记得当年自己小白学它的时候哭爹喊娘的叫它晕针,但是现在来看,指针不就是数值在内存中的地址吗,也是变量嘛,只不过正常变量赋值的是常量或者其他,指针赋值的就是一个个的内存地址,比如

int var = 20;		/* 实际变量的声明 ,赋值为20*/
int *ip = &var;		/* 指针变量的声明 ,赋值为变量var的地址*/

所以,变量名前面带有 ‘*’ 符号的就是指针变量,变量名前面带有 ‘&’ 符号的就是表示该变量的地址。
当然指针还有二级指针等等好多概念,今天先不聊这个,先看看C语言怎么牛叉的利用内存的!

位域

现在告诉你C语言对于内存牛叉在哪:都知道像字符char类型的在很多操作系统里只是一个字节,这个是很小的单位了吧,但是一个字节占了八个占位符啊,这个八个占位符要么是1要么是0(机器识别的信息),如果我要是表达一个布尔值bool值的真与假,我用0和1表示好不好,我这个0和1不要用整数类型的表示,就用那–每一个占位符里面的0或者1好不好!那么我一个字节理论上可以存储8个布尔值变量啊,告诉你,这不是理论这是事实!这就是C语言的位域!

定义:所谓"位域"是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。

大白话就是说,有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。
典型的实例:

  • 用 1 位二进位存放一个开关量时,只有 0 和 1 两种状态。
  • 读取外部文件格式——可以读取非标准的文件格式。例如:9 位的整数。
    定义也和结构的定义差不多:
struct 位域结构名 
{
类型说明符 位域名: 位域长度 
类型说明符 位域名: 位域长度 
类型说明符 位域名: 位域长度
...... 
};

例如:

struct bs{
    int a:8;
    int b:2;
    int c:6;
}data;

说明 data 为 bs 变量,共占两个字节。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。

对于位域的定义尚有以下几点说明:

  1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。
struct bs{
    unsigned a:4;
    unsigned  :4;    /* 空域 */
    unsigned b:4;    /* 从下一单元开始存放 */
    unsigned c:4
}
/*在这个位域定义中,a 占第一字节的 4 位,后 4 位填 0 表示不使用,b 从第二字节开始,占用 4 位,c 占用 4 位。*/
  1. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。如果最大长度大于计算机的整数字长,一些编译器可能会允许域的内存重叠,另外一些编译器可能会把大于一个域的部分存储在下一个字中。

  2. 位域可以是无名位域,这时它只用来作填充或调整位置。无名的位域是不能使用的。

struct k{
    int a:1;
    int  :2;    /* 该 2 位不能使用 */
    int b:3;
    int c:2;
};

从以上分析可以看出,位域在本质上就是一种结构类型,不过其成员是按二进位分配的

不过记下位域的需要注意的几点内容后我们再说个C语言对内存更牛逼的事情!
一个内存地址能不能重复利用多存几条不同的信息??就像家里的鞋盒一样哪天我不放皮鞋了把它做成猫咪的小窝好不好!告诉你,不光鞋盒能做个猫窝,内存也能存储多条不同类型的信息!当然多少有点偏差,具体如下:

共用体

共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。
直接上代码:

union Data
{
   int i;
   float f;
   char  str[20];
} data;/*现在,Data 类型的变量可以存储一个整数、一个浮点数,或者一个字符串。这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。您可以根据需要在一个共用体内使用任何内置的或者用户自定义的数据类型。*/

共用体占用的内存应该足够存储共用体中最大的成员。例如,在上面的实例中,Data 将占用 20 个字节的内存空间,因为在各个成员中,字符串所占用的空间是最大的。所以data共用体的内存大小就是20个字节!
同一时间只使用一个变量 就像鞋盒不能既装皮鞋又装喵咪一样

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   data.i = 10;
   data.f = 220.5;
   strcpy( data.str, "C Programming");
 
   printf( "data.i : %d\n", data.i);
   printf( "data.f : %f\n", data.f);
   printf( "data.str : %s\n", data.str);
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming

在这里,我们可以看到共用体的 i 和 f 成员的值有损坏,因为最后赋给变量的值占用了内存位置,这也是 str 成员能够完好输出的原因。正确使用应该像下面一样:

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   data.i = 10;
   printf( "data.i : %d\n", data.i);
   
   data.f = 220.5;
   printf( "data.f : %f\n", data.f);
   
   strcpy( data.str, "C Programming");
   printf( "data.str : %s\n", data.str);
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

data.i : 10
data.f : 220.500000
data.str : C Programming

在这里,所有的成员都能完好输出,因为同一时间只用到一个成员。

最后最后,再贴上一张图片,看完后马上和链表联系上了!!!

这里写图片描述

猜你喜欢

转载自blog.csdn.net/Mihongzhong/article/details/82109097