C语言处理INT_MIN和LONG_MIN时如何处理void*转换?

问题描述 投票:0回答:1

我正在尝试编写一个能够使用

void*
函数打印
write
的函数。您可以在下面看到我的代码,适用于某些场景,但当我尝试使用
INT_MIN
LONG_MIN
甚至
INT_MAX
等值时,它会失败。

static int write_hex(unsigned char *buffer, int i)
{
    char    tmp;
    int     leading_zero;
    int     counter;

    leading_zero = 1;
    counter = 0;
    tmp = "0123456789abcdef"[buffer[i] / 16];
    if (tmp != '0' || !leading_zero)
    {
        write(1, &tmp, 1);
        leading_zero = 0;
        counter++;
    }
    tmp = "0123456789abcdef"[buffer[i] % 16];
    if (tmp != '0' || !leading_zero)
    {
        write(1, &tmp, 1);
        leading_zero = 0;
        counter++;
    }
    return (counter);
}

int handle_pointer(va_list args)
{
    int             i;
    int             counter;
    void            *ptr;
    unsigned char   *buffer;
    
    ptr = va_arg(args, void*);
    buffer = malloc(sizeof(ptr));
    ft_memcpy(buffer, &ptr, sizeof(ptr));
    i = 0;
    write(1, "0x", 2);
    counter = 2;
    while (buffer[i])
    {
        counter += write_hex(buffer, i);
        i++;
    }
    free(buffer);
    return (counter);
}

测试失败的结果:

args:      [" %p %p ", INT_MIN, INT_MAX]
printf:    [ 0x80000000 0x7fffffff ] = 23
ft_printf: [ 0x 0xffffff7f ] = 15
c hex
1个回答
0
投票
  • 您使用的是 LE 机器。所以 0x7FFFFFFF 被存储为 0xFF,FF,FF,7F。这就解释了

    0xffffff7f

  • while (buffer[i])
    没有任何意义,因为它会导致你在遇到0x00字节时停止打印,例如0x80000000的第一个字节。这就解释了
    0x
    。这也意味着您可能会阅读超出预期的内容并导致未定义的行为。

#include <limits.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

static const char *hex_syms = "0123456789abcdef";

#define STDOUT 1

static size_t write_hex_reversed( size_t n, void *buffer ) {
   unsigned char *p = (unsigned char *)buffer + n;

   for ( size_t i = 0; i < n; ++i ) {
      --p;
      {
         char hex_sym = hex_syms[ *p / 16 ];
         write( STDOUT, &hex_sym, 1 );
      }
      {
         char hex_sym = hex_syms[ *p % 16 ];
         write( STDOUT, &hex_sym, 1 );
      }
   }

   return n * 2;
}

// `n` takes place of the format string in this simpler code.
static size_t handle_pointer( size_t n, ... ) {
   va_list argp;
   va_start( argp, n );

   for ( size_t i = 0; i < n; ++i ) {
      if ( i )
         write( STDOUT, " 0x", 3 );
      else
         write( STDOUT, "0x", 2 );

      void *p = va_arg( argp, void* );
      write_hex_reversed( sizeof( p ), &p );
   }

   return n * ( 3 + sizeof( void * ) ) - 1;
}

int main( void ) {
   void *int_min_as_ptr = (void*)(uintptr_t)(unsigned)INT_MIN;  // Why???
   void *int_max_as_ptr = (void*)(uintptr_t)(unsigned)INT_MAX;  // Why???
   handle_pointer( 2, int_min_as_ptr, int_max_as_ptr );
   write( STDOUT, "\n", 1 );
}
© www.soinside.com 2019 - 2024. All rights reserved.