[英]Recoding printf %p with write function, no printf
I am currently working on a task where I need to print the address of a variable.我目前正在处理需要打印变量地址的任务。 It would be easy to use printf %p but I am only allowed to use write from unistd.
使用 printf %p 很容易,但我只能使用 unistd 的写入。
I tried casting the pointer in to an unsigned integer and uintptr_t and then converting it into a hexadecimal number.我尝试将指针转换为无符号 integer 和 uintptr_t,然后将其转换为十六进制数。 With uintptr_t it works but with an unsigned integer it only prints half of the address.
使用 uintptr_t 它可以工作,但使用无符号 integer 它只打印地址的一半。 Maybe someone can explain me why this is the case?
也许有人可以解释我为什么会这样?
I also saw some solutions using ">>" and "<<" but I didn't get why that works.我还看到了一些使用“>>”和“<<”的解决方案,但我不明白为什么会这样。 It would be nice if someone can explain a solution using "<<" and ">>" step by step, because I am not sure if I am allowed to use uintptr_t.
如果有人可以逐步解释使用“<<”和“>>”的解决方案,那就太好了,因为我不确定是否允许我使用 uintptr_t。
this is the code I use to cast it into a unsigned int / unitptr_t / unsigned long long (I know that ft_rec_hex is missing leading 0's):这是我用来将其转换为 unsigned int / unitptr_t / unsigned long long 的代码(我知道 ft_rec_hex 缺少前导 0):
void ft_rec_hex(unsigned long long nbr)
{
char tmp;
if (nbr != 0)
{
ft_rec_hex(nbr / 16);
if (nbr % 16 < 10)
tmp = nbr % 16 + '0';
else
tmp = (nbr % 16) - 10 + 'a';
write(1, &tmp, 1);
}
}
int main(void)
{
char c = 'd';
unsigned long long ui = (unsigned long long)&c;
ft_rec_hex(ui);
}
It looks like only half of the address is printed because the "unsigned integer" you used has only half size of uintptr_t
.看起来只打印了一半的地址,因为您使用的“无符号整数”只有
uintptr_t
的一半大小。 (note that uintptr_t
is an unsigned integer type) (注意
uintptr_t
是无符号 integer 类型)
You can use an array of unsigned char
to store data in a pointer variable and print that to print full pointer withput uintptr_t
.您可以使用
unsigned char
数组将数据存储在指针变量中并打印它以使用put uintptr_t
打印完整指针。
Using character types to read objects with other type is allowed according to strict aliasing rule .根据严格的别名规则,允许使用字符类型读取其他类型的对象。
#include <stdio.h>
#include <unistd.h>
void printOne(unsigned char v) {
const char* chars = "0123456789ABCDEF";
char data[2];
data[0] = chars[(v >> 4) & 0xf];
data[1] = chars[v & 0xf];
write(1, data, 2);
}
int main(void) {
int a;
int* p = &a;
/* to make sure the value is correct */
printf("p = %p\n", (void*)p);
fflush(stdout);
unsigned char ptrData[sizeof(int*)];
for(size_t i = 0; i < sizeof(int*); i++) {
ptrData[i] = ((unsigned char*)&p)[i];
}
/* print in reversed order, assuming little endian */
for (size_t i = sizeof(int*); i > 0; i--) {
printOne(ptrData[i - 1]);
}
return 0;
}
Or read data in a pointer variable as unsigned char
array without copying:或者将指针变量中的数据作为
unsigned char
数组读取而不复制:
#include <stdio.h>
#include <unistd.h>
void printOne(unsigned char v) {
const char* chars = "0123456789ABCDEF";
char data[2];
data[0] = chars[(v >> 4) & 0xf];
data[1] = chars[v & 0xf];
write(1, data, 2);
}
int main(void) {
int a;
int* p = &a;
/* to make sure the value is correct */
printf("p = %p\n", (void*)p);
fflush(stdout);
/* print in reversed order, assuming little endian */
for (size_t i = sizeof(int*); i > 0; i--) {
printOne(((unsigned char*)&p)[i - 1]);
}
return 0;
}
It would be easy to use printf %p but I am only allowed to use write from unistd.
使用 printf %p 很容易,但我只能使用 unistd 的写入。
Then form a string and print that.然后形成一个字符串并打印出来。
int n = snprintf(NULL, 0, "%p", (void *) p);
char buf[n+1];
snprintf(buf, sizeof buf, "%p", (void *) p);
write(1, buf, n);
Using a pointer converted to an integer marginally reduces portability and does not certainly form the best textual representation of the pointer - something implementation dependent.使用转换为 integer 的指针会略微降低可移植性,并且肯定不会形成指针的最佳文本表示 - 这取决于实现。
With uintptr_t it works but with an unsigned integer it only prints half of the address.
使用 uintptr_t 它可以工作,但使用无符号 integer 它只打印地址的一半。
unsigned
is not specified to be wide enough to contain all the information in a pointer. unsigned
未指定为足够宽以包含指针中的所有信息。
uintptr_t
, when available (very common), can preserve most of that information for void
pointers. uintptr_t
在可用时(非常常见)可以为void
指针保留大部分信息。 Good enough to round-trip to an equivalent pointer, even if in another form.足以往返到等效指针,即使是另一种形式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.