我被问到一个面试问题:给出一个6字节的输入,它来自一个大端机器,请实现一个函数转换/转换为8字节,假设我们不知道运行这个函数的机器的endian 。
问题的关键在于测试我对于endianess的理解,因为有人问我是否在此问题之前知道了endianess。
我不知道如何回答这个问题。例如我需要先填充6个字节到8个字节吗?如何?这是我的代码。这是对的吗?
bool isBigEndian(){
int num = 1;
char* b = (char*)(&num);
return b ? false:true;
}
long long* convert(char* arr[]){ //size is 6
long long* res = (long long*)malloc(long long);//...check res is NULL...
if (isBigEnian()){
for(int i = 0; i< 6; i++)
memset(res, i+2, arr[i]);
}
else {
for(int i = 0; i< 6; i++)
memset(res, i+2, arr[6-1-i]);
}
return res; //assume caller will free res.
}
更新:为了回答我的问题不明确,我刚刚找到了一个链接:Convert Bytes to Int / uint in C,其中包含类似的问题。根据我对此的理解,主持人的结束确实很重要。假设输入是:char array [] = {01,02,03,04,05,06},那么如果host是little endian,则输出存储为00,00,06,05,04,03,02,01 ,如果是大端,输出将存储为00,00,01,02,03,04,05,06,在这两种情况下,0000都在开头填充。
我现在是一种理解:在另一台机器中,假设有一个数字xyz = 010203040506因为它是bigendian而01是MSB。所以它存储为char array = {01,02,03,04,05,06},其中01具有最低地址。然后在这台机器上,如果机器也是大端。它应该存储为{00,00,01,02,03,04,05,06},其中01仍然是MSB,因此它被转换为相同的数字int_64 xyz2 = 0000010203040506.但如果机器是小端,它应该存储为{00,00,06,05,04,03,02,01},其中01是MSB具有最高地址,以便int_32 xyz2 = 0000010203040506。
如果我的未成年人不正确,请告诉我。任何人都可以告诉我为什么0000总是在开始时填充,无论什么结束?如果这台机器是小端,那么不应该在最后填充,因为00是大多数符号字节?
答案 0 :(得分:1)
我不明白为什么你认为malloc是必要的。为什么不这样呢?
long long convert(unsigned char data[]);
{
long long res;
res = 0;
for( int i=0;i < 6; ++i)
res = (res << 8) + data[i];
return res;
}
答案 1 :(得分:1)
在继续之前,您应该要求澄清。
究竟意味着什么转换?用0填充每个字符?用0的前缀每个字符?
我将假设每个char应该以0为前缀。这是一个可能的解决方案:
#include <stdint.h>
#include <limits.h>
#define DATA_WIDTH 6
uint64_t convert(unsigned char data[]) {
uint64_t res;
int i;
res = 0;
for (i = 0; i < DATA_WIDTH; i++) {
res = (res << CHAR_BIT) | data[i];
}
return res;
}
要将0添加到每个字符,我们可以在for:
中使用它res = (res << CHAR_BIT) | (data[i] << 2);
在采访中,您应该始终注意解决方案的限制。此解决方案假定实现提供uint64_t
类型(C标准不要求)。
输入是大端的这一事实非常重要,因为它可以让您知道data[0]
对应于最重要的字节,并且它必须保留在结果中。这个解决方案与目标机器的字节顺序无关。