文本里英雄联盟段位符号号怎么消掉?

C语言总结——段位结构体与补码 - 推酷
C语言总结——段位结构体与补码
最近在进行C语言复习,不借助课本死知识,试图直接通过某些方式进行推理验证,来得出一些听过的和没听过的、还有忘记的结论。
比较浅,适合初学者看。但也有一些不容易发现的小规律能够涨姿势。
1.直接上题,这也算一个面试题吧,让你解释打印结果:
struct bit
int main()
char *c=(char*)&s;
cout&&sizeof(bit)&&
cout && s.a &&endl&&s.b&&endl&&s.c&&
printf(&%x&,a);
这题简单一点,告诉你输出是多少(或者难一点,也可以直接让你猜输出),然后让你解释输出为什么是:
root@v:/usr/local/C-test/analysis# ./a.out
ffffffffroot@v:/usr/local/C-test/analysis#
如果直接就看懂了,请无视这篇帖子。。。
我一分析就分析错了?这都
?退一步两步,然后根据答案也没说对~!
这个题不难,答不对其实是一些基础知识淡忘和遗漏造成的。
马虎大意看错行:
要注意,第一个4是sizeof输出的,由于没加文字性描述,容易误认4为第一个输出(最主要原因是最后一个没换行,linux输出容易忽略那一行,认为前三个是abc第四个是-1,其实第五个才是-1),到时候就更摸不着头脑了——当然,有电脑时你可以自己加文字描述,在纸上不会出现命令行干扰,这个问题可以解决。
2.引用一段关于段位结构的定义(精简版):
&&& 位结构定义的一般形式为:&
&&&& struct位结构名{&
&&&&&&&&& 数据类型 变量名: 整型常数;&
&&&&&&&&& 数据类型 变量名: 整型常数;&
&&&& } 位结构变量;&
& 其中: 数据类型
是int(unsigned或signed)。 整型
是0~15, 表示二进制位的个数, 即
表示有多少位
变量名是选择项, 可以不命名, 这样规定是为了排列需要。&
&&& 例如: 下面定义了一个位结构。&
unsigned incon: 8;
/*incon占用低字节的0~7共8位*/
unsigned txcolor: 4;/*txcolor占用高字节的0~3位共4位*/
unsigned bgcolor: 3;/*bgcolor占用高字节的4~6位共3位*/
unsigned blink: 1;
/*blink占用高字节的第7位*/
位结构成员的访问与结构成员的访问方式是相同的,访问上例位结构中的bgcolor成员可写成:&
&&&&& ch.bgcolor&
&&& 注意:&
&&& 1. 位结构中的成员
定义为unsigned,
定义为signed,&
当成员长度为1时
, 会被认为是unsigned类型
。因为单个位不可能具有符号。
(实测:int默认)
&&& 2. 位结构中的成员
数组和指针
位结构变量(不是位结构变量的成员变量)
数组和指针, 如果是指针, 其成员访问方式同结构指针。&
&&& 3. 位结构总长度(位数), 是各个位成员定义的位数之和,& 可以超过两个字节。&
&&& 4. 位结构成员可以与其它结构成员一起使用。&
struct info{
char name[8];
unsigned state: 1;
unsigned pay: 1;
&&& 上例的结构定义了关于一个工从的信息。其中有两个位结构成员, 每个位结构成员只有一位, 因此只占一个字节但保存了两个信息, 该字节中第一位表示工人的状态, 第二位表示工资是否已发放。由此可见使用位结构可以节省存贮空间。
光参考这些定义,是解决不了这个题的。
下面看看另一个问题,补码~~
3.计算机存储形式——补码
printf(&%x&,a);
首先,看到那个printf了吧,其他都是cout,突然来个printf,是不是很突兀?更绝的是,此处定义了一个a,跟前边根本没关系。
其实,它是题目的提示信息(不是提示的话突然搞这么个输出语句不是蛋疼么,看来这和高考一样,有出题和答题技巧
),-1输出的ffffffff是提示信息,它提示了你计算机的存储形式——用%x控制输出16进制能看清它在计算机中的的存储形式是补码。
那么什么是补码呢?也算基础知识了,这里就不详细说什么原码、反码、补码的定义和区别了,直接上原码补码换算方法:
补码,顾名思义,互补,补全,也可以参考“集合”的定义,一个全集中有子集A,A和否A,两者相补刚好满。说白了这叫模运算。比如二进制中单个位上进行的就是模运算,1+1 == 2,进位10或者不进位0,原来的位上取都取0.
以八位二进制为例,模为2的八次幂,即 + 1,没法用1 表示,因为没那么长~~
正数(补码和原码相同):+11
二进制(这里还不涉及符号,只是二进制数):
原码(第一位为符号位,负数符号位1):
小结:正数不变,负数除符号位,变反+1,总之,原码补码相加应该等于模的倍数。
4.分析原题
有了段位结构体和补码的基础后,再来分析原题:
废话就不多说了,还是设立对照组,利用printf打印参数发现规律和问题。经过多次改进,终于弄出一个比较完整有效的参照实验:
#include&stdio.h&
#include&iostream&
struct bit{
//看看int默认是有符号还是无符号?
int main(){
char *c = (char*) &s;
printf(&before assignment : s is %x\n&,*c);
printf(&and a/b/c is :\n&);
std::cout && s.a && std::endl && s.b && std::endl && s.c && std::
printf(&s.a:%x\ns.b:%x\ns.c:%x\n&,s.a,s.b,s.c);
*c = 0x99;
printf(&after assignment : s is %x\n&,*c);
printf(&sizeof(bit) s is %d\n&,sizeof(bit));
std::cout && s.a && std::endl && s.b && std::endl && s.c && std::
printf(&s:%x\n&,s);
printf(&s.a:%x\ns.b:%x\ns.c:%x\n&,s.a,s.b,s.c);
before assignment : s is ffffffc9
and a/b/c is :
s.c:fffffffe
after assignment : s is ffffff99
sizeof(bit) s is 4
s.b:ffffffff
s.c:fffffffc
PS:赋值前(before assignment):s is ffffffc9尾数c9不是固定的,根据源代码的组织不同,可能影响到内存分配从而造成区别。编译中出现过69、89和c9,但是前边的ffffff是固定的。
可以看到虽然struct bit中只有3+2+3 == 8 个比特位,
但是还是占用了4个字节
,共32个比特位(但是这不影响用一个char指针就给他们三个赋值,因为他们三个占用的一个字节在整个struct bit中的地址最小(
),char指针正好指向那个地址)。
由于改进了实验代码,可以直接从结果看出,struct bit中低8位是被赋值0x99了,
弄成0xffffff了
整个struct bit声明时就存在的。从现在看,无法撼动!!!
特例:除非用指针改——比如*(c+1) = 0x00,手贱的我还是试了,用
*(c + 1) = 0x00;
不成功。怀疑有保护,
不过因为已经证实前边的那堆default产生的ffffff对结果没影响,暂时也就没必要深究了。
s.a,s.b,s.c分别占用几个bit位,就按几个bit位算,不干前边的事。想想也是,那样的话也太悲剧了吧,头一个比特变量(比如s.a)永远受前边影响(s.c:11 11 110),没法算准,特例之中还有特例,用std::cout来操作s.a,s.b,s.c是没事了,但是用其他
不匹配的指针操作,
printf(&before assignment : s is %x\n&,*c);
printf(&s.a:%x\ns.b:%x\ns.c:%x\n&,s.a,s.b,s.c);
的打印结果:
s.b:ffffffff
s.c:fffffffc
那么再来分析打印结果,我先做个小假设
(蓝色为实际上错误的假设)
赋值前:十六进制:0xfffffc9
后八位分给s.a、s.b、s.c:
打印结果是:1、1、-2
赋值后:十六进制:0xffffff99
后八位分给s.a、s.b、s.c:
打印结果是:1、-1、-4
明显不对~!!!所以呢?顺序有误,s.a和s.c应该调换一下!
即,赋值后:
s.a为001,
s.c为110,
s.b还是01。
这样再按补码看(不用补到八位或32位,有几位算几位),110是-2;100是-4;01和001都是1;11是-1。就对上号了
这个故事告诉我们:结构体中,不光先声明的常规变量地址更低,先声明的比特位也在同地址中更低的地方
——话说回来,这只是个特例,刚好他们总共才占一个地址,如果扩展到比特位占用多个地址(就是总和大于8bit)的情况下,必然要遵循这个
个人能力有限,没有深究两个问题:
1.我使用*(c + 1) = 0x00;或者*(c - 1) = 0x00;都无法改变struct bit中前边24位中的1,说是保护不知道妥当否,还是方法不对。
2.既然s.a等都只有两三位,他们在寄存器中是怎么操作的,先从栈中提取出来,放寄存器,补全,操作完,再放回去?
因为使用了%al低8位操作,又用了$0xfffffff8等补全操作,所以暂且假设是刚好能对s.a,s.b和s.c分别操作而互不影响,具体应该能从这些值中计算,推测一二,但是先写到这吧,没推,扯得有点远。
有些也没看太懂,比较生偏的movzbl等(也能都的到差不太多的AT&T用法)。
=& 0x8048634 &main()+16&: and
$0xfffffff8,%eax
0x8048637 &main()+19&: or
0x804863a &main()+22&: mov
%al,0x14(%esp)
0x804863e &main()+26&: movzbl 0x14(%esp),%eax
0x8048643 &main()+31&: or
$0x18,%eax
0x8048646 &main()+34&: mov
%al,0x14(%esp)
0x804864a &main()+38&: movzbl 0x14(%esp),%eax
0x804864f &main()+43&: and
$0x1f,%eax
0x8048652 &main()+46&: or
$0xffffffa0,%eax
0x8048655 &main()+49&: mov
%al,0x14(%esp)
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致Java文本框里输入汉字字母标点符号的的时候如何让他们在换行的时候右边对齐 - Java Web开发当前位置:& &&&Java文本框里输入汉字字母标点符号的的时候如何让他Java文本框里输入汉字字母标点符号的的时候如何让他们在换行的时候右边对齐&&网友分享于:&&浏览:0次Java文本框里输入汉字字母标点符号的的时候怎么让他们在换行的时候右边对齐如题,在要输出的文本框中,汉字和字母标点符号所占的宽度是不同的,怎么才能让他们在换行的时候右边对齐?------解决思路----------------------可以尝试下在onkeydown上加个方法,判断输入的是中文标点字符的时候就改成英文的,或者反过来,如果要中英文都可以输出可以试试输入英文标点时前面加个空格,让他长度和中文标点一样长------解决思路----------------------&input&type="text"&style="background:'#efefef';&text-align:right"&/&&&这样能行么?------解决思路----------------------首先你要确定业务上是否需要?
然后再从技术角度来实现。
因为有全角和半角的关系,所以他们会参差不齐。
如果你固定了大小,强使他们对齐,就会出现字的变形,变窄,变难看。
所以最好的解决办法就是输入的时候保持对齐。如果是用户输入的话就限制他。
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 1234567891011 Copyright & &&版权所有lol查段位名字后面女生符号怎么消去_百度知道
lol查段位名字后面女生符号怎么消去
我有更好的答案
这是YY登录盒子绑定的
只需要登录盒子然后解除就好了
上YY在绑定游戏那取消绑定就行了
这消不掉的`(*∩_∩*)′
其他类似问题
为您推荐:
回归线的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁EXCEL中如何插入直径符号?
EXCEL中如何插入直径符号?
09-03-19 &
插入---符号 基本希腊语 或者直接 alt+248
请登录后再发表评论!
插入---符号  基本希腊语  或者直接 alt+248
请登录后再发表评论!
EXCEL文本里,工具栏上有一个&插入&的选项,在菜单里有一个&符号&的选项,里面有很多种符号,选择你想要的那种符号就可以了.
请登录后再发表评论!
插入---符号 基本希腊语 或者直接 alt+248
请登录后再发表评论!
插入---符号 基本希腊语 或者直接 alt+248
请登录后再发表评论!
ALT+42677注,按数字时是小键盘上的数字哟
请登录后再发表评论!

我要回帖

更多关于 英雄联盟段位符号 的文章

 

随机推荐