问题描述
/*
* Change the value pointed to by ptr byte-by-byte so that when returned as an
* integer the value is 351351.
*
* Hints: Recall that an int is 4 bytes and how little-endian works for
* multibyte memory storage. We suggest starting by converting 351351 into
* binary/hexadecimal.
*
* ALLOWED:
* Pointer operators: *,&
* Binary integer operators: -,+,*
* Shorthand operators based on the above: +=,*=,++,--,etc.
* Unary integer operators: !
*
* disALLOWED:
* Pointer operators: [] (Array Indexing Operator)
* Binary integer operators: &,&&,|,||,<,>,<<,>>,==,!=,^,/,%
* Unary integer operators: ~,-
*/
我需要按照上述要求编写一个函数。我不能使用循环,数组索引和其他东西。我了解字节序概念。所以我有整数351351。十六进制为0x 00 05 5C 77
。因此,使用小端序机,它会存储为77 5C 05 00
,对吗?
int endianExperiment(int * ptr) {
char * bytePtr;
// Your code here
// 0x 00 05 5C 77
int num = 0;
bytePtr = (char * ) ptr;
return num;
}
到目前为止,这是我的职责。我在char中获得了指针参数的地址(所以只有2个字节),然后将其存储在bytePtr中。但是我被困住了。我尝试了几种选择,但没有任何效果。请帮忙。
同样,对于little-endian,该数字以最低有效数字存储在数组的最低索引处。但是要访问它(数字地址),它仍然是最低的索引吗?还是包含第一个字节的索引?我需要在哪里指向指针?
解决方法
“不允许”列表有很多限制。例如,通常的方法是将字节位屏蔽(&)和位移位(>)到相反的字节序位置,但是这些操作是不允许的。其余的(%)也不允许,否则我们可以使用它来模拟位屏蔽。那还剩下什么呢?听起来下面是一种允许的方法(并要求通过“逐字节”更改值来暗示):
-
首先将输入修剪为char *指针,方法是:
char* bytePtr = (char*)ptr
。假设字节序的本地字节序很少,*bytePtr
是整数*ptr
的最低有效字节。 -
使指针指向num的最高有效字节:
char* dest = ((char*)&num) + 3
。 -
将
*bytePtr
分配给*dest
。完成一个字节。 -
递增
bytePtr
和递减dest
。 -
为剩余字节再重复步骤3和4 3次。但是请不要使用循环来执行此操作,因为不允许使用
<
,只需写下展开的重复项即可。
最后,num
包含具有相反字节序的整数。
编辑:我可能误解了这个意图。感谢busybee指出这一点。重新读取后,问题陈述为“逐个字节更改ptr指向的值,以便当返回整数时,值为351351。”
听起来我们应该将特定的int值351351写入*ptr
。而且,我们应该按字节进行操作,如果我们只能*ptr = 351351
进行操作,那将太容易了。
351351的十六进制形式为0x00055c77,如罗曼所说。
-
假设计算机为低端字节序,则写入字节0x77、0x5c,0x05、0x00,从最低地址0x77开始:
*bytePtr = 0x77
,*(bytePtr + 1) = 0x5c
,依此类推。 > -
但是,如果计算机为大端字节序,则字节需要以相反的顺序排列,以便将
*ptr == 351351
解释为int值:*bytePtr = 0x00
,*(bytePtr + 1) = 0x05
,等等。
最好是可移植地编写代码,以便在小端和大端机器上工作。 There are multiple methods来检测机器的字节顺序,包括一些使用允许的操作在C中工作的机器。因此,我们可以检测到字节序大小不大,然后按照适当的顺序继续写入上述字节。 (除了大大小以外,其他字节序也是可能的,并且全面的解决方案也可以解决这些问题,但如今它们很少见。)