2015-04-03 61 views
0

我试图使用指针来移动一个充满十六进制值的内存区域。我使用的是uint8_t指针,以确保它一次只指向1个字节。我想要转到特定位置(从起始位置偏移字节数)并存储一组长度为1,2,4或8个字节的字节。然后我想解释并打印该值作为有符号或无符号十进制(由枚举参数确定)。类型转换指针来改变其大小(以字节为单位)

我认为我可以简单地将指针从1字节的uint8_t更改为字节数的正确大小(例如对于8 btyes的uint64_t),然后存储该值(因为我不能只是打印它一次一个字节,我需要评估整个字节/一组字节)。这是我到目前为止有:

void showValueAtOffset(FILE* Out, const uint8_t* const baseAddr, uint32_t Offset, Sign Sgn, uint8_t nBytes) {//------------------doesn't work---------------- 
    uint8_t *p = baseAddr;//create a pointer that points to the first byte of memory in the array 
    for(int i = 0; i < Offset; i++){//use a for loop to move p to the location indicated by Offset 
     p++; 
    } 
    if(nBytes == 1){ 
     //pointer p already has the correct typecast for the number of bytes 
     uint8_t N = *p;//store the value of the byte 
     if(Sgn == SIGNED){ 
      int8_t result = N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      fprintf(Out, "%u ", N);//print the value 
     } 
    } 
    else if(nBytes == 2){ 
     uint16_t q = (uint16_t) p;//create the pointer q with the correct typecast for the number of bytes 
     uint16_t N = *q;//store the value of the bytes 
     if(Sgn == SIGNED){ 
      int16_t result = N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      fprintf(Out, "%u ", N);//print the value 
     } 
    } 
    else if(nBytes == 4){ 
     uint32_t q = (uint32_t) p;//create the pointer q with the correct typecast for the number of bytes 
     uint32_t N = *q;//store the value of the bytes 
     if(Sgn == SIGNED){ 
      int32_t result = N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      fprintf(Out, "%u ", N);//print the value 
     } 
    } 
    else if(nBytes == 8){ 
     uint64_t q = (uint64_t) p;//create the pointer q with the correct typecast for the number of bytes 
     uint64_t N = *q;//store the value of the bytes 
     if(Sgn == SIGNED){ 
      signed int result = (signed int) N; 
      fprintf(Out, "%d ", result);//print the value 
     } 
     else{//if UNSIGNED 
      unsigned int result = (unsigned int) N; 
      fprintf(Out, "%u ", result);//print the value 
     } 
    } 
    else{ 
     //this should not happen according to the preconditions 
    } 
    fprintf(Out, "\n"); 
} 

这不工作,我得到一些错误,如“无效的类型arguement‘一元*’(有‘uint32_t的’)”和“警告:一个指针转换为整数大小不同“。

我在做什么错?

+0

您正在将'uint8_t *'转换为'uint32_t'(例如),失去了该类型的指向性。你仍然需要担心指针的对齐。在许多机器上,如果它没有指向8字节的边界(地址不是8的倍数),那么你不能使用'uint64_t *',否则你的访问会变得非常严重。 (例如,在DEC Alpha中,一个未对齐的访问触发了一个系统调用,它可以为你解决问题,但是比对齐访问慢得多,通常根本不需要系统调用。) – 2015-04-03 23:36:59

+0

请注意,问题的标题是错误的。你不能改变指针的大小;出于实际的目的,所有数据指针都是相同的大小,而不管它们指向什么。你可以改变的是指向的对象的大小。如前所述,你可以做些什么的警告,但如果风是公平的,你可以改变存储在'uint8_t *'中的值到存储在'uint64_t *'中的值,然后使用生成的指针在一次操作中获取64位(8字节)的数据。 – 2015-04-03 23:55:37

+0

好吧,我在typecasts(uint32_t *)中添加了一个*,除了8字节的部分(uint64_t的部分)外,它们现在都在工作。 当我看结果时,它看起来像是被截断为一个32位整数而不是一个64位整数。我认为这是因为我在打印之前将它作为'signed int'和'unsigned int'进行转换。 我应该如何保持64位大小并正确打印它? – user3743206 2015-04-03 23:57:07

回答

2

错误的直接来源是您应该使用uint16_t *q = (uint16_t *) p;而不是uint16_t q = (uint16_t) p;,它是指向另一个指针类型的指针类型,然后将其解析。

但是,修改后的代码依赖于机器结构,存在大/小端和对齐问题。简而言之,代码将在x86机器上运行,但可能因未对齐的内存访问而崩溃,或在其他体系结构上产生错误的数字。一种便携式的方法是这样的:

uint32_t to_uint32_be(const void* num) 
{ 
    const uint8_t *p = num; 
    uint32_t res = 0U; 
    int i; 
    for (i = 0; i < 4; i++) 
     res = (res << 8) + p[i]; 
    return res; 
} 

在上面的“是”的代码代表大端,即数据存储在网络字节顺序最显著字节。