c++ - 使用 %s 调用 printf 并传递一个零长度的 char* 是未定义的行为吗?

标签 c++ printf language-lawyer undefined-behavior

下面代码中的第三行是否定义明确?

char* result = new char[0];                                                                                                                                                                                                                    
printf("%d\n", strlen(result));                                                                                                                                                                                                                                                        
printf("%s\n", result);                                                                                                                                                                                                                                                                
delete[] result;

当我运行代码时,我得到了预期的输出(长度为 0,后跟两个换行符)。但是,我不确定这是否是一种明确定义的行为,还是我只是走运。

三线调用是否明确?

最佳答案

简答:未定义的行为

长答案:在 C++ 中,分配大小为 0 的数组将产生一个指向没有元素的数组的有效指针。 来自标准(取自 this answer ):

来自 5.3.4/7

When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

来自 3.7.3.1/2

The effect of dereferencing a pointer returned as a request for zero size is undefined.

(强调我的)

这意味着无法正确读取(或写入)从 new T[0] 返回的指针请求。

两者都是 strlenprintf对于字符串格式“%s”,定义为适用于以特殊 NUL 结尾的字符串特点。他们需要从提供的指针中读取字符序列来尝试找到这个 NUL字符以便正确操作(这会导致 UB,因为这需要取消引用指针)。这些行为在 C 标准中定义,因为 C++ 标准将大多数 C 库类型/函数的定义委托(delegate)回 C 标准。

printf访问%s被定义为执行以下操作:

来自 C11 标准 §7.21.6.1/6

If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.

Characters from the array are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the array, the array shall contain a null character.

这需要访问数组(这将是 UB,因为指针对于解引用无效)

奖金

由于使用了strlen,您的示例代码实际上在第二行引入了UB。 ,出于与上述类似的原因。

strlen被定义为执行以下操作:

来自 C11 标准 §7.24.6.3/3:strlen功能

Returns

The strlen function returns the number of characters that precede the terminating null character.

这是 UB,原因与使用 printf 相同.

关于c++ - 使用 %s 调用 printf 并传递一个零长度的 char* 是未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51050366/

相关文章:

c++ - 在变量中切换文件 (cpp)

c++ - 为什么 stoi 比没有 -O3 的 stringstream 慢得多?

c++ - 存储指向同一模板类的模板类型的指针

c++ - 调用 vsnprintf 时的核心转储

c - Chez Scheme 中的 FFI,用于具有可变参数的 C 函数(varargs)

c++ - 非连续对象数组

java - Java7 规范中的语法真的等同吗?

c++ - 如果我只想要结构良好的工作区但不一定要分开编译,如何在 C++ 中组织头文件/代码文件?

c - 使用 printf() 添加不需要的空格/行的格式化输出 - C 编程

c++ - 具有不同指向成员指针的参数的非类型模板参数的特化是否保证是唯一的特化?