C/C++的零散知识(五)

8 篇文章 0 订阅

1.关于打开文件的问题
现在有一个问题,我想用二进制形式打开一个exe可执行文件,并且输出其中的二进制数据,应该怎么办。不讲太多,直接上代码。

#include <stdio.h>
#include <ctype.h>

int main()
{
	FILE *fp;
	char ch[50];
	int ch1;
	scanf("%s",ch);
	fp=fopen(ch,"rb");
	if(fp==NULL)
		printf("ERROR");
	else
	{
		ch1=fgetc(fp);
		while(ch1!=EOF)
		{
			//if(isalnum(ch1)!=0)
				printf("%x",ch1);
			//else
				//printf(" 00");
			ch1=fgetc(fp);
		}
	}
	return 0;
}

对该程序进行一些补充,这个程序关键的问题在于,fgetc函数的返回值为一个int类型,如果定义的ch1是char类型的,那么输出时会将fgetc返回的int类型看成对应字符的ascii码,虽然会转化为对应的字符,但是会有很多的缺省,因为在exe文件中(这里特指dos中的exe文件,因为对windows中的exe文件不太了解),开始的若干个字节的文件描述后面通常会跟着一堆的0,这些会被翻译为空字符,不会被显示出来,所以我们将ch1变量写作整型。返回的值正确。

2.关于C中的signed与unsigned的区别
先给个例子,

#include <stdio.h>

 

void f(unsigned char v)

{

    char c = v;

    unsigned char uc = v;

    unsigned int a = c, b = uc;

    int i = c, j = uc;

    printf("----------------\n");

    printf("%%c: %c, %c\n", c, uc);

    printf("%%X: %X, %X\n", c, uc);

    printf("%%u: %u, %u\n", a, b);

    printf("%%d: %d, %d\n", i, j);

}

 

int main(int argc, char *argv[])

{

    f(0x80);

    f(0x7F); 

    return 0;

}

对该程序进行一个简单的补充解释。首先是在内存中,signed与unsigned类型没有本质的区别,都是一个字节,唯一的区别是signed最高位被看成符号位,所以signed的取值范围为-128~127(关于为什么取值为-128,这个是和补码有关的一个人为的规定,详细了解可以去百度查),unsigned不存在符号位的情况,所以取值范围为0到255。主要是符号位,但是在普通的赋值,读写文件和网络字节流都没什么区别,反正就是一个字节,不管最高位是什么,最终的读取结果都一样,只是你怎么理解最高位而已,在屏幕上面的显示可能不一样。
但是我们却发现在表示byte时,都用unsigned char,这是为什么呢?
首先关于byte,这个玩意通常意义上来讲你单单看他,他不存在什么符号。(符号这个玩意是编译器所认为的,就是进行人为规定的)。但是在赋值的时候会有问题。更重要的是如果将byte的值赋给int,long等数据类型时,系统会做一些额外的工作。(事实上来说byte类型在c语言中是存在的,但是我们不推荐用byte类型,一般来说都用unsigned char,就像上面程序所示的那样,下文中的byte类型可以看成unsigned char)如果我们将byte类型赋值给char类型,那么编译器会对最高位进行扩展,如果byte为0x80,那么赋值后,char类型为0xFFFFFF80,这个值实际上是一个补码,计算机中为了方便计算都会以补码保存数据,如果我们把它转换成对应的原码,它的值为0x80000080
也就是1000 0000 0000 0000 0000 0000 1000 0000,这个值为-0x80,如果我们不那么严谨的来看的话,char类型与对应的byte类型的值只差一个符号,值是相同的。这个例子意味着在将byte类型的值赋值给char类型时,系统对char类型的最高位进行了填充,如果byte类型的值的最高位为0,那么系统在char类型中填充时,高位全部为0,如果byte类型的值的最高位为1,那么系统在char类型中填充时,会将最高位填充为1,其余为0,进行求补操作后就会变成类似FFFF这样的高位数据。如果将被同一个byte类型赋值的char与unsigned char同时用%c进行输出的话,他们的值是相同的,这个原因可能是编译器在通过%c输出一个变量是只看前一个字节的信息,如果只看前一个字节的信息,char与unsigned char 类型的值是相同的,所以翻译为同一个字符。(按道理来说如果你给一个例如0x80的值给char与unsigned char他们都不会被翻译为任何的字符,但是在我的vc中他们被翻译为了一个罗马字符,很有可能ascii码有额外的扩展,这个就不深究了。)同样的,如果把一个值为0x80的byte类型变量先赋值给char与unsigned char,之后用char与unsigned char分别为int类型的变量赋值,最后用%d输出,发现被char类型赋值的int输出为-128,被unsigned char类型赋值的int输出128,对照着上面的解释,出现如此结果的原因应该明了了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值