打印指向 uchar 值的指针

Posted

技术标签:

【中文标题】打印指向 uchar 值的指针【英文标题】:Printing pointer-to-uchar values 【发布时间】:2017-11-28 05:04:03 【问题描述】:

当我在 64 位机器上运行以下代码时(编译器 clang)

typedef unsigned char byte;

void foo ( byte* a ) 
    std::cout << sizeof(a) << std::endl;
    printf( "%x\n", a );
    std::cout << a << " " << a+1 << std::endl;


int main() 

byte a[2];

a[0] = 'A'; a[1] = 'c';
foo( a );

return 0;

输出是

8
ea4c3a9a
Ac c

第一行是有意义的,因为这是一个 64 位指针。但是我不明白为什么第二行只有 4 个字节,或者最后一行。谁能指出第二条和第三条输出线背后的原因?

编辑:好的,那么问题是:如何正确创建以空字符结尾的字节数组,并且这样做会“正确”最后一行?

【问题讨论】:

仅供参考,编译器warn 关于printf a 不是以 null 结尾的字符串,%x 不是有效的指针格式。行为未定义。 关于您的最后一个问题: 1. 提供足够的存储空间 - 例如byte a[3]; 2. 在最后一个内容字节之后存储一个空终止符 - 例如a[0] = 'A'; a[1] = 'c'; a[2] = 0;a[2] = '\0'; 也可以,但实际上也是一样的。)要分配以 null 结尾的字符串,还有一种更简单的方法:byte a[3] = "Ac";。因此,"Ac" 被编译为 3 字节 - 空终止符被静默添加。您没有在您的 C 或 C++ 书籍中阅读所有这些内容吗?在任何一种情况下都应该提到它——可能在前 50 页的某个地方。 “但是我不明白为什么第二行只有 4 个字节”:"%x"unsigned 值的格式化程序。无论您在参数中输入什么 - 它都会准确读取 sizeof (unsigned) 字节并打印它们。试试sizeof (unsigned),你可能会得到4。(当然不是所有的64位C/C++编译器都坚持32位ints。)格式化程序参考:printf, fprintf, sprintf, snprintf, printf_s, fprintf_s。 顺便说一句。因此printf() 函数系列被认为既强大又危险:如果您的额外参数与格式化字符串中描述的内容不完全匹配(所有这些% 序列),那么可能会发生意外的事情。因此,C++ 提供了一种类型安全的替代方案,即&lt;&lt;(和&gt;&gt;)运算符。顺便提一句。您是否已经决定是学习 C 还是 C++? (我会先专注于其中一个。尽管后者是从前者发展而来的,但还是有一定的差异。) 【参考方案1】:

如前所述,行为是未定义的。不过,我们可以尝试了解这里发生了什么。 第 2 行是 a 的前 4 个字节的结果。当 %x 在文字字符串中时,printf 函数需要一些无符号类型,因此将值读入无符号整数或长整数。 第 3 行只是一个 char* 的打印。虽然 a 最初是一个 c 字符串,但它被传递给函数一个 unsigned char *。您可以对其执行指针运算。 例如,如果 a 的地址是 0x1000,那么: std::cout &lt;&lt; a 将首先打印从 0x1000 到 '\0' 的字符,&lt;&lt; a + 1 部分将打印从 0x1001 到 '\0' 的字符。

幸运的是,第三个字符(不是你的,因为 a 只有 2 个字符长)可能是 '\0'。

对于您的问题,您可以非常简单地创建一个空终止字节数组。在启动时,您可以分配一个文字字符串,如下所示:

byte a[3] = "Ac"; 总大小为 3,因为 '\0' 需要一个字节。

或者你可以启动它 strcpy,或者从文件 fprintf 中读取。重要的是要说第三行是空终止字节*的正确输出(它是“偶然”发生的)。如果您觉得它不正确,那么您可能正在寻找应该以不同方式编写的东西。

编辑: 既然我了解了您想要做什么(即打印 a 和 a + 1 的地址),那么您应该使用 std::cout:

#include <iostream>

int main()

    unsigned char a[2];
    std::cout << static_cast<void*>(a) << " " << static_cast<void*>(a + 1) << std::endl;

    return 0;

输出是:

0x7ffcd22f9700 0x7ffcd22f9701

【讨论】:

> std::cout &lt;&lt; a 将首先打印从 0x1000 到 '\0' 的字符,因此,此行为特定于 cout,对吗?切换到printf( "%p %p\n", a, a+1 ); 对我有用。

以上是关于打印指向 uchar 值的指针的主要内容,如果未能解决你的问题,请参考以下文章

C语言中关于二维数据指针的问题?

在 GDB 中取消引用双指针(指向值的指针)

Arduino指向结构变量的指针和指向结构数组的指针打印输出

如何从该指针获取指针指向的值的地址

c++ 指针参数:创建指向值的副本是不是有意义,然后再次将副本存储为指针?

为啥指针+1包含的内存地址与被指向的值的地址+1不同