RSS订阅优然探索
你的位置:首页 » 技术笔记 » 正文

C语言中的数据类型、指针、unsigned与signed、位操作有关知识(自编QQ铺垫篇之二)

选择字号: 超大 标准 发布时间:2014-5-14 10:28:28 | 作者:admin | 0个评论 | 人浏览

C语言是一门语法非常严格的计算机编程语言。

C语言中为什么在声明变量时需要确定这个变量的类型?

因为C语言中变量的操作是和内存紧密相关的,变量的类型确定了它在内存中的结构,比如int型变量是内存中的连续4个字节(通常是这样),char型变量时内存中的一个字节,而一个结构体占用的内存长度则在它定义好的时候就确定了。

(说起来好像是废话。)

为什么所有变量的指针都相当于一个32位整数(int),在定义一个指针变量时却要声明它指向的变量的类型?

因为程序只有知道它指向的变量的类型才知道怎么对这个变量进行操作。

比如你定义一个结构体

struct rectangle

{

int x1,y1,x2,y2;

};

定义一个rectangle变量:rectangle MyRect;

然后定义一个指针

rectangle *pt_rect=&MyRect;

然后你写int left=pt_rect->x1的时候,程序知道去pt_rect指针指向的变量中读取x1对应的那段内存;

试试定义一个int *test;

如果你强行写下test->x1;编译器会报错,因为int类型中没有对应的x1元素。

来玩玩数组的降维:

定义一个整型数组:

int x[3][4];

然后把int x[3][4]变成长度为12的一维数组y;

可能最容易想到的是先定义一个int y[12]用两层循环来把x数组中的数挨个赋值到y数组中,这完全不是什么好办法。了解数组的会知道,数组在内存中是连续的,x和y数组都有12个数,都是整形,这样它们在内存中的存放形式完全没有区别。然后还得了解x和y作为数组名,其实都是指针,只不过系统为它们保存了不同的信息:

(为了不浪费内存,所以只定义一个整形指针int *y;而不定义为int y[12]了;)

x指向一个3x4规模的二维数组,都是整形元素,且x是指针常量,无法被重新赋值;

y可以指向一个任意的整数;

然后把y指向x数组的头部:y=x;

但是编译器会报错或者警告,说类型不匹配,怎么办呢?

这样:y=(int *)x;对x的类型做了强制转换,程序认为赋给y的就是一个一维数组的指针。

然后就可以这样使用这个“一维数组”了:y[i];不过现在系统不知道y的长度了,请自己注意0<=i<12;

再举一个例子:

char x[4]={0x12,0x34,0x56,0x78};

怎么把x数组转换为整形0x12345678?

由之前讲的可以知道x数组在内存中连续摆放,占用了一个整形的长度,也就是与整形变量0x12345678在内存中的摆放形式一样;

也就是说我们只要让程序认为x那儿就是一个整形变量就可以了;

定义一个int *n;

令n=(int *)x;

然后*n就是x数组对应的整型值0x12345678了。

解释一下:x是指向char的指针,(int *)x是对x做了一个强制转换,让系统认为这个指针指向的是整型变量,然后赋给整形指针变量n;

然后*n是对指针取指向内存的值,程序按照int的约定规则取值,取出来的就是0x12345678这个数了。

注意星号的作用:在定义变量的时候表示该变量为指针,而在其他时候表示对某个指针取该指针指向变量的值。

其实定义数据类型只是为了告诉程序或者操作系统要以怎么样的规则来操作一块内存,对指针熟悉之后,你可以几乎不用定义任何数据类型,完全用空指针和位操作来实现你想实现的操作。

————————————————————分割————————————————————

下面讲述位操作里面的移位操作;

“<<”符号表示对变量中的二进制位依次向左移,x<<n表示对x变量中的二进制位左移n位。然后超出的部分被截断,低位补0;

“>>”符号表示右移,超出的截断,高位补上;

假设int x=1;那么x<<8==256,这是高位没有溢出的情况,溢出的话换算为2进制来模拟移动也可以计算出结果;

假设int x=11111111 11111111 11111111 11111111;

x>>1的结果是多少?

是01111111 11111111 11111111 11111111吗?

x>>n的结果是前面有n个0吗?

不,结果都是11111111 11111111 11111111 11111111;

你会发现不管n等于多少,x都没有变化,还是32个1。

原因是操作系统在对内存进行移位时会保持变量符号不变,所以对首位是1的整数(负数)进行右移位操作时,最高位总是补1,而不是补0;

所以为了在进行移位操作时不出现意外情况,请把变量声明为unsigned;

另外有时候对char型变量赋整数值并对char型变量比较大小的时候,也可以声明为unsigned char来避免出现意外情况。

例如假设令char a=0x8F;

然后if(a==0x8F)printf("a eqauls 0x8F");

发现不会有输出,为什么呢?

因为声明char的时候默认为有符号型,a在这儿被赋值为10001111,当做有符号型来看的话相当于-113(负113),当然不等于0x8F这个正数。

以上这些内容也是之后自编QQ的一些数据处理会涉及到的问题。

标签:

猜你喜欢

发表评论

必填

选填

选填

必填,不填不让过哦,嘻嘻。

记住我,下次回复时不用重新输入个人信息

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。