问题 这个C代码是否有定义的行为?


这是一个思想实验,不是生产代码,也不是良好的编码风格。

假设我们有这个功能

int find_process_pid_by_name(char* name, int* threads_in_process);

返回 PID 一个命名的进程,也总是存储 threads_in_process 在所述进程中运行的线程数。

一个懒惰的程序员,只对此感兴趣 PID,写这段代码

int pid = find_process_pid_by_name("a process name", &pid);

它会触发未定义的行为吗?


8788
2017-07-16 23:30


起源

我想如果你访问 threads_in_process[i], i = 1,2,3.. 在你的功能 find_process_pid_by_name 这将是未定义的行为! - user007
它定义明确。正如答案中所提到的,在函数返回之前有一个序列点,这意味着任何先前的副作用都已发生。 - Filipe Gonçalves
严格来说,你正在通过一个 const char * 一个需要的功能 char *;如果函数修改了传递的内容,则会得到未定义的行为。 - Jonathan Leffler


答案:


不 - 我不认为这是不确定的行为。在调用函数之前有一个序列点(在参数和表示被调用函数的表达式已被评估之后),并且在被调用函数返回之前还有另一个序列点。任何副作用 pid 由函数执行的函数已在函数完成返回之前完成。然后将该函数的结果赋值给 pid。毫无疑问,该功能改变了分配的位置。我没有看到任何调用未定义行为的东西。

我假设被调用的函数处理 int * 参数作为指向单个值的只写指针。如果它从单个值读取,我们需要知道 pid 之前已经初始化(正式;在实践中,它无关紧要)。在上下文中, pid 尚未初始化;函数的结果将初始化它。因此,如果函数从其指针参数读取,从技术上讲,您有未定义的行为。如果函数将指针视为多元素数组的开头并访问超出第0个元素,则存在问题。但这些问题有些超出了问题/讨论的预期范围。


10
2017-07-16 23:40





是的,我相信这段代码定义明确。在将返回值复制到调用上下文之前,函数末尾有一个序列点。所以函数将首先分配给 pid 间接通过 threads_in_process,然后它将返回,然后返回值将被分配给 pid


1
2017-07-16 23:41