C语言(数据类型)

编程语言中的数据类型,那是一个刚开始接触代码的初学者会学习的第一个概念,但是我们对这个概念真的理解彻底吗?我看不一定。

请看下面这段会被实验室大神,或者技术装逼犯看不起的定义语句:

int sum;

也难怪,这么简单的定义语句,实在没什么好讲的,即便是对一个零基础小白,解释完这条语句也是三言两语的事儿,不信你听听:“定义了一个称之为 int 类型的变量sum,在以后的日子里,sum就专门用于存放整型数据”。

以上的解说说的不差,但没有戳中要害。仅仅是将类型理解为计算机存的放各种不同数据,不足以深刻理解诸如指针运算、类型转换(尤其是指针类型转换)、数组与指针等关系。

不卖关子了,更帅的理解如下:“所谓类型,是我们在使用一块内存之前,跟系统事先说好的一个约定”。

对,类型是一个约定。上面的整型变量的定义,其实应该这么理解:在我们的死皮赖脸下,系统答应给我们分配一块起名为 sum 的内存,并一开始就约定——以后这块内存专门用来存放整型数据。

就这么一个君子协定,奠定了两个最基本的要素:

A) sum 这块内存的大小尺寸(永远不变)

B) sum 这块内存的解释方式(偶尔变心)

这里要注意的是,第一个要素一旦定下来,以后不管你怎么折腾这块内存,其大小尺寸是永远不会变的。但关键是第二要素,这块内存的解释方式,在某些时候是可以“反悔”的!

其实这跟现实生活中的办公楼租赁一样,租之前必须跟物业说清楚要租来干嘛,办公可以,做厨房肯定是不被允许的。但是你租了之后,玩点小花招,今天当成仓库,明天偷偷做几顿饭,也许可以瞒天过海。

内存也一样,说好的用来存放整型,那么系统就会严格遵守你们的约定,将这块内存的每一位都对应地解释为 2 的次幂,然后进行累加。而你却可以瞒着系统,将其他任意数据“塞”到这块内存中。

也就是说,即便你要将一头大象塞进去也是可以的,编译器阻止不了你,但是一旦你对a这块内存进行引用,编译系统会将里面的东西一概认为是int型数据,因为一开始定义的时候大家就说好了嘛!

struct elephant // 一头大象 { char c; double f; int i; char s[5]; }; int a; struct elephant x = {'w', 3.14, 100, "hey"}; a = *( (int *)&x ); // 试图将一头大象塞进 a 里面! printf("%d\n", a); // 打印出一个毫无意义的垃圾值

仔细看代码,注意到我们居然将一个结构体变量x塞进一个整型变量a里面(当然只能塞进去一部分)!只要对类型稍作转换,就可以做到,这样变量a里面存放的实际上是跟整型数据风牛马不相及的东西,语法上没有任何问题,只是数据变得没有意义。

此例旨在告诉你,甭管是什么变量,都只是一块内存,里面都是一大串101010110101……序列而已,语法上我们可以随意地操纵这些内存,以及里面的内容,但是逻辑上我们必须使得他们有意义,所以还必须考虑每块内存的本职工作:存储某一种在定义时约定好的类型的数据。

再来,经常有人要讨论 void 型指针的用法,look:

void *p;

void 指针p的含义是:其目标类型是未定的,因为目标类型未定,就相当于目标的大小尺寸无从得知,其内存解释方式更加无从谈起,因此当然就无法对其进行任何运算(包括加减法和解引用运算),因此 void 型指针的在使用之前,必须将其转换为一个目标类型确切的指针,比如:

*(int *)p = 100;

这样才能将 100 放到其指向的目标内存中,因为 p 在使用前,进行了所谓的类型转换,转换成 int * 了! 啥意思呢? 就是跟系统(物业)说:嘿哥们!原先我们说好只办公(void型指针)的,现在我们有点特殊情况,临时改造成厨房(int型指针),请你知悉并配合!

就这么着,系统就按照 int 型指针的语法来解释 p 了。 这下清楚数据类型强制转换的意思了吧。

原文发布于微信公众号 - 秘籍酷(mijiku040)

原文发表时间:2019-05-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券