Gui*_*ean 7 c c99 undefined-behavior language-lawyer implicit-conversion
我不明白 C99 标准中的以下未定义行为:
函数定义中的调整参数类型不是对象类型 (6.9.1)
从标准来看,函数的参数需要在两种情况下进行调整:
在第二种情况下,函数的调整参数确实不是对象(据我所知,标准区分了对象和函数):
标识符可以表示一个对象;一个函数;一个标签或一个结构的成员,联合...
您能否澄清这一点并提供此类 UB 的示例?
C 标准的第一个引用是不正确的。这听起来像
\n\n\n\xe2\x80\x94 函数定义中调整后的参数类型不是完整的对象类型(6.9.1)
\n
那就是你漏掉了这个词complete。
例如,在与其定义类型不同的函数声明中,您可以指定不完整的对象类型,例如
\nvoid f( size_t, size_t, int [][*] );\nRun Code Online (Sandbox Code Playgroud)\n在此函数声明中,第三个参数的声明不是完整的对象类型,因为数组元素的大小未知。
\n这是一个演示程序
\n#include <stdio.h>\n\nvoid f( size_t, size_t, int [][*] );\n\nvoid f( size_t m, size_t n, int a[][n] )\n{\n for ( size_t i = 0; i < m; i++ )\n {\n for ( size_t j = 0; j < n; j++ )\n {\n a[i][j] = n * i + j;\n }\n }\n}\n\nvoid g( size_t, size_t, int [][*] );\n\nvoid g( size_t m, size_t n, int a[][n] )\n{\n for ( size_t i = 0; i < m; i++ )\n {\n for ( size_t j = 0; j < n; j++ )\n {\n printf( "%d ", a[i][j] );\n }\n putchar( '\\n' );\n }\n}\n\nint main(void) \n{\n size_t m = 2, n = 3;\n int a[m][n];\n \n f( m, n, a );\n g( m, n, a );\n \n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n它的输出是
\n0 1 2 \n3 4 5 \nRun Code Online (Sandbox Code Playgroud)\n在程序中这两个函数声明
\nvoid f( size_t, size_t, int [][*] );\nRun Code Online (Sandbox Code Playgroud)\n和
\nvoid g( size_t, size_t, int [][*] );\nRun Code Online (Sandbox Code Playgroud)\n具有不完整对象类型的参数声明。
\n您不能使用这样的声明,即其定义位于同一类型,例如
\nvoid f( size_t m, size_t n, int a[][*] )\n{\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\n因为将第三个参数调整为指针后,编译器无法确定指针类型。也就是说指针将具有不完整的对象类型int ( * )[]。