我的意思是像"(%d%%%d) some text %s , %d%% %x %o %#x %#o \n"
. printf 系列函数以某种方式知道他们需要从这个字符串中获得多少个参数,因此不需要单独的参数。这个功能是在 c/c++ 中以单独的函数形式提供的,所以我可以编写自己的类似 printf 的函数吗?(是的,我故意放这些百分比来强调它可能变得多么复杂,所以它不是简单地计算百分比字符)
3 回答
family的问题printf
在于它不安全,它并不真正知道或关心字符串或参数列表中有多少格式元素。
printf
家庭使用一种叫做“可变函数”的东西;只有一个参数被命名(格式字符串),其他参数从堆栈中获取,而不考虑它们的类型或大小 - 它们的类型是从格式字符串推导出来的,这使得它类型不安全,并通过迭代找到要使用的参数数量字符串并查找所有格式说明符,这使其参数编号不安全。您可以编写可变参数函数;语法是
void foo(...);
后来你可以使用这些宏和类型,虽然如果你使用 C++,你应该使用 C++11 的可变参数模板而不是 C 可变参数函数,因为可变参数模板是类型安全的 - 你不会在任何地方丢失类型信息,并且通用引用(但不太感谢它们)它们比可变参数函数更强大。
printf 系列函数只知道一个参数,第一个参数......
它基本上扫描字符串,每次遇到它理解的格式说明符时,它都会从参数列表中提取该大小的下一个参数......这是一个容易损坏的行为。想象:
printf("%i",someInt); // fine
printf("%i",someLong); // depending on endianness and sized
// of those types could be the high or low 32 bits(probably)
printf("%i %i",someInt); // depending on abi could crash, read a int sized chunk
// of stack, or a register that would correspond to that
// parameter.
所以本质上不安全..
您应该注意警告,并且在编写可移植代码时执行以下操作:
size_t t = 5; //can be 32 or 64 bit depending on arch.
printf("%ull",(unsigned long long)t);
编辑。我想我只回答了一半......您可以定义自己的可变参数函数,以下添加count
参数数量并返回结果。
int sumList(int count, ...);
int main(int argc, const char * argv[])
{
printf("the answer is: %i",sumList(4,1,2,3,4));
return 0;
}
int sumList(int count, ...)
{
va_list args;
va_start(args, count);
int sum = 0;
for (int i = 0; i<count; i++) {
sum += va_arg(args, int);
}
va_end(args);
return sum;
}
不,没有用于解析 printf 样式格式字符串的标准库函数。如果您想编写自己的字符串格式化函数,那么我强烈建议您不要遵循 printf 示例。由于其他答案中提到的原因,它本质上是不安全的。由于某些语言中的词序发生了变化,因此本地化也存在问题。就个人而言,我会使用模板编写一个类型安全的函数并复制 .NET 样式的格式字符串。(实际上,我确实这样做了——工作量很大,但也很有趣。)