在同一调用中打印 %n 的值 - 毫无意义?
printf the value of %n in the same call - senseless?
我在 cppreference.com 找不到printf
规范的以下部分的意图:
每次转换的操作后都有一个序列点 规范;这允许在同一%n中存储多个%n结果 变量并打印 %n 之前存储的值 叫。
这读起来好像一个(甚至几个)%n
转换说明符的结果可以打印在同一个printf
语句中。 但是我无法找到如何实现这一点,因为所有传递给printf
调用的参数都是在输入printf
的主体之前被评估的(参数评估后有一个序列点)。因此,在printf
有机会用"到目前为止写入的字符数"覆盖该变量的值之前,%n
将写入的变量的值进行评估:
#include <stdio.h>
int main( int argc, char* argv[] )
{
int n = 0;
printf("Hello, world!%n (%d first n); %n (%d second n)", &n ,n, &n, n);
// will print out "Hello, world! (0 first n); (0 second n)"
return 0;
}
我的问题:如果没有任何机会"在同一调用中打印 %n 之前存储的值",那么printf
规范的相应部分是不是毫无意义或具有误导性?
c99标准声明的实际含义是什么:
7.19.6 格式化输入/输出函数 (1) 格式化的输入/输出函数的行为应像在 与每个说明符关联的操作。
是为了减少获得未定义行为的"机会"吗?
这个问题被标记为 c++ 和 c,因为我认为这个主题对这两种语言的适用方式相同。
这可能很疯狂,但我认为以下内容是合法的:
char s[2];
s[1] = ' ';
printf("Hi, world!%hhn%s", s, s);
%hhn
获取指向字符的指针。它将10
(到目前为止写入的字符数)写入s[0]
。然后它打印字符串s
,相当于"n"
或(char[]){ 10, 0 }
(假设 ASCII)。
由于您正确识别的原因,您的代码确实只打印零。
标准中的声明仍然是必要的,因为其他地方的笼统措辞是,如果一个对象被写入不止一次而没有干预序列点,则程序的行为是未定义的。实际上,该语句是必要的,以说明您的代码没有未定义的行为(不像,例如,i = i++;
)。
可以想象编译器将对printf
的调用转换为一系列单独的fputs()
调用,其中包含通过调用转换处理程序计算的字符串片段。 此实现可能会在打印n
的值之前将值存储到n
中。 这会不符合规定吗?
现代编译器已经对printf()
进行了小的优化,例如将printf("Hello worldn");
转换为puts("Hello world");
,将printf("n");
转换为fputchar('n');
。 他们还检查格式字符串和参数一致性...进一步的优化将导致上述结果。
- 数组索引的值没有增加
- 'short int'持有的值溢出,但"自动"不会溢出?
- 是默认情况下分配给char数组常量的值
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 为什么我无法更改"set<set>"循环中的值<int>
- 有效地使用std::unordered_map来插入或增加键的值
- <streamsize>C++ 中 numeric_limits::max() 的值
- 为什么不能修改对象中的值?另外,我如何改进此链表?
- 无法获取webot::PositionSensor对象中位置传感器的值
- 正在将无序映射设置为无序映射的值
- 着色器纹理值与创建纹理时写入的值不同
- 无法按cpp中的值返回矢量
- 指针没有更新它在void函数内部指向的值
- x86 - 为什么编译器在下一条指令中插入看似毫无意义的JMP?
- OpenGL 中的动态加载着色器毫无意义吗?
- 如果编译器只能执行恒定折叠,则是毫无意义的
- 在同一调用中打印 %n 的值 - 毫无意义?
- Netbeans 中的C++:许多毫无意义的"unexpected token"提示
- C++ 指针参数:创建指向的值的副本,然后再次将副本存储为指针是否有意义
- 将函数的返回类型声明为 T&&& 是否毫无意义?