我指的是像"(%d%%%d) some text %s , %d%% %x %o %#x %#o \n"
这样的字符串。 printf系列函数以某种方式知道它们需要从这个字符串中需要多少个args,因此不需要单独的参数。这个功能是用单独的函数在c / c ++中提供的,所以我可以编写自己的类似printf的函数吗? (是的,我故意将这些百分比用于强调它有多复杂,所以不是简单地计算字符百分比)
答案 0 :(得分:2)
printf
系列的问题在于它不安全,并且它不确实知道或关心字符串或参数列表中有多少格式元素。
printf
家庭使用名为"变量函数&#34 ;;只有一个参数被命名(格式字符串)而其他参数是从堆栈中获取的,不考虑它们的类型或大小 - 它们的类型是从格式字符串中推导出来的,这使得它类型不安全,并通过迭代来查找要使用的参数数量。字符串并查找所有格式说明符,这使得参数号不安全。你可以编写可变函数;语法是
void foo(...);
以后你可以使用those macros and types,虽然如果你使用C ++,你应该使用C ++ 11的可变参数模板而不是C变量函数,因为可变参数模板是类型安全的 - 你不要&# 39; t在任何地方放松类型信息,并且universal references(但不完全感谢他们)它们比可变函数更强大。
答案 1 :(得分:1)
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;
}
答案 2 :(得分:1)
不,没有用于解析printf样式格式字符串的标准库函数。如果你想编写自己的字符串格式化函数,那么我强烈建议不要遵循printf示例。由于其他答案中提到的原因,它本质上是不安全的。由于某些语言中的词序变化,它也存在本地化问题。就个人而言,我会使用模板编写一个类型安全的函数,并复制.NET格式的字符串。 (实际上,我做了这样做 - 这是很多工作但也很有趣。)