OI中神奇的神器fillchar
传说,Pascal中有一个函数——fillchar。这是高手们装*用的利器,也是大家的神器(大家好才是真的好)。
神器介绍:
百度百科说:“Fillchar是Turbo/Borland Pascal的System单元的一个标准过程,它的使用格式是:FillChar(var X; Count: Word; value),它的功能是,把指定变量X在内存段中所占的低Count个字节赋为相同的值value, 其中value是填充的值,只能是Byte、Char或Boolean等单字节类型的值。在Free Pascal中稍加扩展为FillChar(var X; Count: Longint; value), 功能没变。”听起来很没意义,搞不懂究竟是个什么鬼吧?
其实这就是个内存块赋值函数,举个例子,这里有一段代码:
fillchar(a,sizeof(a),233);//a:array[1..100] of byte
等效于:
for i:=1 to 100 do a[i]=233;
显而易见,这个函数减少了编码工作量,而且不用在写代码时抬头看数组a的范围。看到这里,你肯定认为你已经懂了,打开了FPC,键入了如下代码:
fillchar(a,sizeof(a),1);//a:array[1..100] of longint
回头用Debug会发现,a中的值不为1,而是一个很大的值(16843009)10=(0000001000000100000010000001)2。没错,你被fillchar坑了。它的工作机理并有你想象的这么简单。
回顾上文,看见红色的两个类型名了吗?再回顾上文,看见“单字节”三个字了吗?byte是个单字节类型,范围是0-255,但longint不是,它是一个4字节类型,范围是-2^31~2^31。而FPC把这个数组仍当做了一个byte等单字节类型的数组来处理。对于一个longint,其在内存中的块分布是这样的:(第1行第n列的数表示第n字节所表示的数,第2行第n列的数表示第n字节所表示数的二进制形式)
| 0 | 0 | 0 | 0 |
| 00000000 | 00000000 | 00000000 | 00000000 |
经过一次fillchar(a,sizeof(a),1)以后,fillchar对每个字节中的数都进行了赋值,于是内存就变成了这样。
| 1 | 1 | 1 | 1 |
| 00000001 | 00000001 | 00000001 | 00000001 |
把下面那行转化为10进制,就是16843009。
再看一个例子,如果是fillchar(a,sizeof(a),128)呢?
| 128 | 128 | 128 | 128 |
| 10000000 | 10000000 | 10000000 | 10000000 |
呵呵,按刚才那样的转换,结果应该是2155905152。但是Debug又能够让你傻眼,结果是-2139062144。
你忘记longint是个有符号数了吗?“1”处在符号位上,于是整个数就变成了负数。而负数又是补码来表示。当符号位为1时,补码的补码就是原数的绝对值。转一下,看看是不是这样?
神器应用:
这里分点来描述:
- 给数组赋值0,这是最常用的了,代码:fillchar(a,sizeof(a),0);//a可以是任何类型的数组,原因读者可以自己探究
- 给数组赋值-1,比较常用,代码fillchar(a,sizeof(a),255);//a为longint数组
- 给数组赋值±INF,赋值INF的值为127,-INF的值为128,要求数组类型为longint
- 给boolean,char或byte,shortint数组赋初值,这里的初值就是最后存在数组里的值。
- 其实fillchar不止可以用在数组上,也可以用在一个数上。那么,可以用这个类似BUG的玩意完成二进制重写2、4、8次后值的问题,而且只要一句话,比位运算更简单(虽然这好像没有什么卵用)。
神器的亲戚:
神器是有亲戚的!
pascal中,fillchar的亲戚有fillword,filldword,分别可以用在填充integer、longint数组,而且所见即所得——填充后的数与第三个参数一样(只是故意不早告诉你)。
c++中,它的亲戚有memset,用法应该与fillchar一样(但是支持有符号数作为参数)。
OI中神奇的神器fillchar的更多相关文章
- 浅谈OI中的底层优化!
众所周知,OI中其实就是算法竞赛,所以时间复杂度非常重要,一个是否优秀的算法或许就决定了人生,而在大多数情况下,我们想出的算法或许并不那么尽如人意,所以这时候就需要一中神奇的的东西,就是底层优化: 其 ...
- 浅谈分治算法在OI中的应用
分治虽然是基本思想,但是OI中不会出裸分治让你一眼看出来,往往都是结合到找规律里面. 先来个简单的: 奇妙变换 (magic.pas/c/cpp) [问题描述] 为了奖励牛牛同学帮妈妈解决了大写中 ...
- [技术]浅谈OI中矩阵快速幂的用法
前言 矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中,矩阵的运算是数值分析领域的重要问题. 基本介绍 (该部分为入门向,非入门选手可以跳过) 由 m行n列元素排列成的矩形阵列.矩阵里的 ...
- OI中常犯的傻逼错误总结
OI中常犯的傻逼错误总结 问题 解决方案 文件名出错,包括文件夹,程序文件名,输入输出文件名 复制pdf的名字 没有去掉调试信息 调试时在后面加个显眼的标记 数组开小,超过定义大小,maxn/ ...
- GCC&&GDB在OI中的介绍
序言 这本来是用Word写的,但是后来我换了系统所以只能用markdown迁移然后写了...... $\qquad$本文主要投食给那些在Windows下活了很久然后考试时发现需要用命令行来操作时困惑万 ...
- OI中的莫比乌斯反演
OI中的莫比乌斯反演 莫比乌斯函数 想要学习莫比乌斯反演,首先要学习莫比乌斯函数. 定义 莫比乌斯函数用\(\mu(x)\)表示.如果\(x\)是\(k\)个不同质数的积,则\(\mu(x) = (- ...
- 浅谈OI中的提交答案
在OI中,题目有三类: 传统题 交互题 提交答案题 今天来了解一下第三类 概述 传统题:给你一个题面,你需要交一个程序,评测姬会用你的程序运行你看不到的一些测试点,用输出和正确答案比较 提交答案题:给 ...
- OI中组合数的若干求法与CRT
OI中组合数的若干求法与CRT 只是下决心整理一下子呢~ 说明:本篇文章采用\(\binom{a}{b}\)而不是\(C_{a}^b\),以\(p\)指代模数,\(fac_i\)指代\(i!\),\( ...
- OI中字符串读入和处理
OI中字符串读入和处理 在NOIP的"大模拟"题中,往往要对字符串进行读入并处理,这些字符串有可能包含空格并以\n作为分割,传统的cin >> scanf() 等等,不 ...
随机推荐
- 【Stage3D学习笔记续】真正的3D世界(五):粒子特效
先看效果,按下空格键添加粒子特效: 一般而言粒子特效的实现都是比较复杂的,且不说实现粒子特效的编码和设计,光是编写一个粒子编辑器就不是简单的一件事,但是作者使用了很取巧的方式来完成,我们接下来深入代码 ...
- Java 判断是否为汉字 判断是否为乱码 判断字符串是否为双整型数字 整数 数字
/** * 判断是否为汉字 * * @param str * @return */ public static boolean isGBK(String str) { char[] ch ...
- UIDatePicker 之显示中文 年月日
picker_start=[[UIDatePicker alloc]initWithFrame:CGRectMake(centerView.frame.size.width/-,centerView. ...
- C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部【转载】
这是最近在做的一个项目中提到的需求,把一个现有的窗体应用程序界面嵌入到自己开发的窗体中来,看起来就像自己开发的一样(实际上……跟自己开发的还是有一点点区别的,就是内嵌程序和宿主程序的窗口激活状态问题) ...
- HDU 5501 The Highest Mark 背包dp
The Highest Mark Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...
- 包管理器Bower使用手冊之中的一个
包管理器Bower使用手冊之中的一个 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.Bower介绍 Bower是一个适合Web应用的包管理器,它擅长 ...
- Introdution to 3D Game Programming With DirectX11 第11章 习题解答
11.1 这道题要注意使用了line strip,由于曾经一直用triangle list,所以在几何渲染的时候easy算错定点描绘的顺序. 贴一些代码,大概就能把这个问题解释清楚了,由于框架还不是特 ...
- javascript 递归之阶乘
阶乘,即5! = 5*4*3*2*1, 先看传统的做法,利用while循环实现: function factorial(num){ var result = num; if(num<0){ re ...
- node.js 浏览器中输出 “hello world”
前段时间花了几个小时,在command面板输出了“hello world”,今天就来说说怎么在浏览器上输入一个地址,然后页面输出“hello world”. 首先要搭建一个基础的 HTTP 服务器 一 ...
- Linq的小知识(一),大家可以学习一下
linq的简介 lLINQ是Language Integrated Query的简称,它是集成在.NET编程语言中的一种特性.已成为编程语言的一个组成部分,在编写程序时可以得到很好的编译时语法检查,丰 ...