【问题标题】:How do I dereference based on size?如何根据大小取消引用?
【发布时间】:2010-10-15 04:40:50
【问题描述】:

我正在尝试打印地址指向的值,但问题是我需要根据传递给我的大小取消引用该指针。所以类似的东西:

void print(Address addr, Int size) {
...
}

我对如何实现这一点有点困惑。有人能指出我正确的方向吗?

编辑: 好的,所以我在想:

char p[80];
memset(p, '\0', 80);
memcpy(p, addr, size);

然后解引用为 *p。如果有更好的方法或者正确的方法,请告诉我

【问题讨论】:

  • 您能详细说明一下吗?您的意思是有时您想将指针取消引用为 32 位 int(例如,如果 size==4),有时作为 64 位 int(如果 size ==8)?还是你追求别的?
  • @Michael:没错。我正在尝试打印这些数字的十六进制表示。

标签: c pointers dereference


【解决方案1】:

你的问题很不清楚。如果您的意思是要从传递的地址转储任意二进制数据,您需要类似:

void print(const unsigned char *addr, size_t size)
{
    while (size--) printf("%.2x", *addr++);
}

或者,如果您的意思是要打印不以 null 结尾的字符数据,请尝试:

void print(const char *addr, int size)
{
    printf("%.*s", size, addr);
}

【讨论】:

  • 我将 const 限定符添加到 char * 参数中。由于函数不(也不应该)修改指针参数的目标,我们可以让编译器的优化器和错误检查了解更多关于内部发生的事情。
【解决方案2】:

如果它是一个数字,我假设它是,你将需要这样的东西:

int n=0;
if (size>sizeof(int)) { return; //int is too small };
for (int i=0;i<size;i++) {
  ((char*)(&n))[sizeof(int)-(i+1)] = ((char*)addr)[size-(i+1)];
}
printf("%d",n);

【讨论】:

  • 这段代码最多有实现定义的行为,更有可能是未定义的行为......
  • 如果size 小于sizeof(int),则n 的部分表示保持未初始化。此外,您应该复制到开头还是结尾是实现定义的(取决于字节序)。
【解决方案3】:

您可以在例程中使用 switch 语句:

switch (size) {
   case 1: print( *(char*)pointer); break;
   case 2: print( *(short*)pointer); break;
   case 4: print( *(long *)pointer); break;
   case 8: print( *(__int64*)pointer); break;
   default: puts( "unsupported);
}

("print" 是打印各种大小整数的例程,可能使用 C++ 多态性)

一个复杂的解决方案是使用 C++ 模板,例如使用参数类型 Integer 在调用时由实际变量类型替换。然后,此例程可能会作用于此 Integer 变量的大小(可能从 1 到 8 不等,如果您自己实现更长的整数,则可能更大)。这种方法的缺点是编译器为每种类型的参数生成一个例程实例,并且依赖于大小的逻辑将导致某些测试的“始终为真”条件。一个简单的方法是始终使用您期望的最长整数类型。

【讨论】:

  • OP 已将其标记为 C 而不是 C++,所以我猜这排除了多态性或重载打印 - 但您的答案背后的原则是可以的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-17
  • 1970-01-01
  • 2015-02-15
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多