how does printf know the address of a CString#39;s character data?(Printf如何知道一个字符串的字符数据的地址?)
本文介绍了Printf如何知道一个字符串的字符数据的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
考虑此代码片段:
struct My {
operator const char*()const{ return "my"; }
} my;
CStringA s( "aha" );
printf("%s %s", s, my );
// another variadic function to get rid of comments about printf :)
void foo( int i, ... ) {
va_list vars;
va_start(vars, i);
for( const char* p = va_arg(vars,const char*)
; p != NULL
; p=va_arg(vars,const char*) )
{
std::cout << p << std::endl;
}
va_end(vars);
}
foo( 1, s, my );
这段代码产生了"直观"的输出"啊哈"。但我不知道这是怎么回事:
- 如果变量函数调用被转换为推送参数的指针,则printf将收到一个被解释为
const char*
的 - 如果变量函数调用正在对它调用
operator (const char*)
,为什么它不为我自己的类调用?
CStringA*
有人能解释一下吗?
编辑:添加了一个虚拟变量函数,该函数将其参数视为const char*
s。请注意,当它到达my
参数时,它甚至会崩溃...
推荐答案
C++98标准的相关文本§5.2.2/7:
在参数表达式上执行左值到右值(4.1)、数组到指针(4.2)和函数到指针(4.3)的标准转换。在这些转换之后,如果参数没有算术、枚举、指针、指向成员的指针或类类型,则程序的格式不正确。如果参数具有非POD类类型(第9条),则行为未定义。
因此正式行为未定义。
但是,给定的编译器可以提供任意数量的语言扩展,而Visual C++确实提供了。关于将参数传递给...
:,MSDN Library记录了Visual C++的行为
- 如果实际参数的类型为Float,则在函数调用之前将其提升为Double类型。
- 任何有符号或无符号的字符、短、枚举类型或位字段都使用整数提升转换为有符号或无符号整型。
- 类类型的任何参数都通过值作为数据结构传递;副本是通过二进制复制创建的,而不是通过调用类的复制构造函数(如果存在)来创建。
这篇文章没有提到有关Visual C++应用用户定义的转换的任何内容。
MSCString
被巧妙地布局,因此它的POD表示恰好是指向其以空结尾的字符串的指针。(sizeof(CStringA) == sizeof(char*)
)当它在任何printf样式函数中使用时,该函数Get只是传递了字符指针。
由于上面的最后一点和CString
的布局,所以这是可行的。
这篇关于Printf如何知道一个字符串的字符数据的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
沃梦达教程
本文标题为:Printf如何知道一个字符串的字符数据的地址?
基础教程推荐
猜你喜欢
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04
- C++,'if' 表达式中的变量声明 2021-01-01
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- 设计字符串本地化的最佳方法 2022-01-01
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01