我试图学习如何(使用)C程序中的指针;我的例子如下:
open(readdata.filename(), 'a')
我试图打印 #include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int * tab = (int*)malloc(sizeof(int)*5);
int a =10;
int *p;
p = &a;
printf("the adress of a is%d \n",&a);
printf("the adress of a using the pointer is%p \n",p);
printf("the adress of tab is%d \n",tab);
}
的地址,a
的地址以及p
的第一个字节开始的位置。
使用tab
时我可以获得十六进制值,但我愿意使用地址的十进制值。
答案 0 :(得分:10)
要打印对象指针的十进制版本,请先将指针转换为整数。最好使用可选类型uintptr_t
。
以下类型(
uintptr_t
)指定一个无符号整数类型,其属性是任何有效的void指针都可以转换为此类型(uintptr_t
)...C11dr§7.20.1.41< / p>
#include <inttypes.h>
uintptr_t d = (uintptr_t)(void *) &a;
然后打印出来。
关于PRIuPTR
printf("%" PRIuPTR "\n", d);
对于C99之前的代码,请考虑直接转换为unsigned long
。 @Barmar
OP后来发表了评论
“...我将尝试操作tab变量,我将测试选项卡中的每个单元格是否为4字节,因此可能会执行tab + 8字节以获取特定单元格的值,此处这是一个简单的例子,带小数对我来说很容易。“
这是一个值得怀疑的方法,因为指针的十进制化可能无法提供预期的连续数值模型。这篇文章可能对学习有好处,但是OP在另一篇文章中提供了更多细节,甚至可以为更高层次的问题提供更好的想法。
答案 1 :(得分:4)
首先,请注意地址通常是“类似数字”但可能不是(例如,记住1980年代16位x86 PC上远程地址的段+偏移概念)。
然后,与指针最相似的整数类型是intptr_t
(已签名)或uintptr_t
(无符号) - 均来自<stdint.h>
。
您可以将其转换为long long
(希望它们不小于指针),例如。
printf("address of a in decimal is %lld\n", (long long) (intptr_t) (&a));
但实际上,你为什么要以这种方式展示地址?我认为不需要它(例如,调试器或链接器通常以hexa显示地址,这可能是%p
所做的。)
请注意,C11标准(参见n1570,§7.21.6.2,p315)对打印指针的%p
没有太多说明:
参数应是指向
void
的指针。指针的值以实现定义的方式转换为打印字符序列。
我正在理解上述内容,其中任何指针的打印Hello ⭔
都是可接受的标准符合行为。在实践中,实现以类似于链接器和调试器的方式打印指针,并且不会以愚蠢的方式表现(但我知道他们可以)。
最后,指针的实际具体“数字”值并不重要,并且从一次执行到下一次执行可能会有很大差异(例如因为ASLR)。
答案 2 :(得分:3)
如果要将指针视为十进制整数,请将其强制转换为unsigned long
并以%lu
格式打印。虽然标准不能保证这一点,但它应该适用于大多数实现。
printf("the address of a is %lu\n", (unsigned long)&a);
答案 3 :(得分:3)
对于打印“地址”(实际上是指针)"%p"
是最常用的方法(请注意void*
必要的强制转换)。如果需要十进制而不是十六进制的地址,可以将指针转换为整数值;这在C中有明确定义(参见this在线C标准草案):
6.3.2.3指针
(6)任何指针类型都可以转换为整数类型。除了 之前指定的,结果是实现定义的。如果 结果不能用整数类型表示,行为是 未定义。结果不必在任何值的范围内 整数类型。
所以代码可能如下所示:
int main(int argc, char *argv[]) {
int a =10;
int *p = &a;
p = &a;
unsigned long long addrAsInt = (unsigned long long)p;
printf("the adress of a is %llu \n",addrAsInt);
printf("the adress of a using the pointer is %p \n",(void*)p);
}
答案 4 :(得分:0)
p是打印指针的转换说明符。使用它。
int a = 42;
printf("%p\n", (void *) &a);
请记住,省略强制转换是未定义的行为,而使用p转换说明符的打印是以实现定义的方式完成的。