我无法printf在cppreference.com上找到以下规范部分的意图:
在每个转换说明符的操作之后有一个序列点; 这允许在同一个变量中存储多个%n个结果,并在同一个调用中先前打印%n存储的值.
这看起来好像一个(甚至几个)%n转换说明符的结果可以在同一个printf语句中打印出来.但我无法弄清楚如何实现这一点,因为传递给调用的所有参数都会printf在printf输入正文之前进行评估(参数评估后有一个序列点).因此,%n之前要评估的printf变量的值有可能用"到目前为止写入的字符数"覆盖此变量的值:
#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;
}
Run Code Online (Sandbox Code Playgroud)
我的问题:如果没有机会"在同一个呼叫中早先打印%n存储的值",那么printf规范的相应部分是否毫无意义或误导?
c99标准声明的实际意义是什么:
7.19.6格式化输入/输出功能(1)格式化的输入/输出功能的行为应与在每个说明符相关的操作之后有一个序列点.
是否减少了获取未定义行为的"机会"?
问题用c ++和c标记,因为我认为这个主题对两种语言应用相同的方式.
关于SO 的最近一个问题 "为什么在这种特定情况下在堆栈上分配大元素不会失败?" 以及关于"堆栈上的大型阵列"或"堆栈大小限制"的一系列其他问题让我搜索标准中记录的相关限制.
我知道C标准没有指定"堆栈",因此它没有为这样的堆栈定义任何限制.但我不知道了,其SIZE_X在void foo() { char anArray[SIZE_X]; ... }标准保证了程序的工作,并发生了什么事,如果程序超出此SIZE_X.
我发现了以下定义,但我不确定这个定义是否实际上是对具有自动存储持续时间的特定支持对象大小的保证(参见此在线C11标准草案):
5.2.4.1翻译限制
(1)实现应能够翻译和执行至少一个包含以下每个限制的至少一个实例的程序:
...
对象中的65535个字节(仅限托管环境中)
这是否意味着实现必须支持一个价值高达65535为SIZE_X像一个功能void foo() { char anArray[SIZE_X]; ... },并且大于任何价值65535的SIZE_X是未定义的行为?
对于堆,调用malloc返回NULL让我控制请求"太大的对象"的尝试.但是,如果程序"请求具有自动存储持续时间的过大对象",我该如何控制程序的行为,特别是如果没有记录这样的最大大小,例如在某些情况下limits.h?那么有可能编写一个便携式功能,如checkLimits()支持"入口屏障",如:
int main() {
if(! checkLimits()) {
printf("program execution for sure not supported in this environment.");
return 1;
} else {
printf("might work. wish you good luck!");
}
...
}
Run Code Online (Sandbox Code Playgroud) 假设我有一个包含几个成员的结构,每个成员属于同一类型.我想通过名称和数组索引安全地访问成员,所以我介绍了一个union包含实际struct和数组的数组,它对应于struct数字和类型方面的成员.请参阅以下代码,其中说明了如何使用以下struct两种方式"查看"以下两种方式union:
#include <iostream>
template<typename elemT>
struct productData {
elemT color;
elemT size;
elemT application;
elemT division;
};
template<typename elemT>
union productDataAsArray {
struct productData<elemT> p;
elemT arr[(sizeof(productData<elemT>) / sizeof(elemT))];
};
int main() {
union productDataAsArray<int> myProduct;
myProduct.p.color = 10;
myProduct.p.size = 20;
myProduct.p.application = 30;
myProduct.p.division = 40;
for (int i=0; i<4; i++) {
std::cout << "elem #" << i << ":" << myProduct.arr[i] << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
是否安全/保证标准假设数组的内存布局对应于内存布局struct …
在下列PROGRAMM的输出1或0,或者是不确定的行为?
int main() {
unsigned char u = 10;
sscanf("1025","%hhu",&u);
printf("u, is it 0 or is it 1? u's value is ... %hhu", u);
}
Run Code Online (Sandbox Code Playgroud)
根据带有长度修饰符(即)的fscanf 转换说明符 ,语义是基于函数的定义和映射到无符号字符的类型指针:%u hh%hhustrtoul
12)转换说明符及其含义是:
"u" 匹配一个可选的带符号十进制整数,其格式与strtoul函数的主题序列的预期格式相同,基本参数的值为10.相应的参数应该是指向无符号整数的指针.
11)长度修饰符及其含义是:
"hh"指定以下d,i,o,u,x,X或n转换说明符适用于带有signed char或unsigned char的类型指针的参数.
但是如果输入序列表示超过8位的整数值,那么会发生什么呢?整数值的哪一部分映射到无符号字符的8位?是否定义它必须是最不重要的部分,它是否依赖于endianess,它是未指定的,还是甚至产生未定义的行为?
我无法相信它是未定义或未指定的行为.这意味着用户输入可能会在程序中引入此类行为scanf("%hhu",&u),并在每次使用scanf看起来荒谬之前检查用户输入.