为什么“strupr”的实现不起作用?

时间:2016-04-02 13:19:16

标签: c gcc

错误的实现(使用gcc编译):

#include <stdio.h>
#include <ctype.h>

char* strupr( char *str )
{
    while(*str) {
        *str++ = toupper(*str);
    }

    return str;
}

int main(void) {

    char string[] = { "Test String!" };
    strupr( string );
    puts( string );

    return 0;
}

该函数以意外的方式更改字符串,其中转换为大写的字符仅从第二个字符开始。

注意str在作业中使用了两次。

1 个答案:

答案 0 :(得分:3)

此实现无效,因为它包含未定义的行为。

解释来自标准第6.5节第2段:

  

在上一个和下一个sequence point之间,一个对象的表达式评估最多只能修改一次存储值。此外,先前的值应该是只读的,以确定要存储的值。

该标准给出了一个表达式的例子,该表达式被认为是未定义的行为以澄清第二句:

a[i++] = i;

在此表达式中,i的值不仅用于确定要存储的新值,还用于确定另一个值的存储位置。

这正是你的表达中发生的事情:

*str++ = toupper(*str);

唯一的区别是你的表达式使用指针,并在其间调用toupper

这个要求似乎是随意的,但它有一个原因。 C标准允许编译器在++调用之前或之后使toupper的副作用可见,以使编译器编写者具有最大的灵活性。如果没有str在表达式中使用的限制,这可能导致不同平台上的不同行为,因此标准作者决定完全禁止它。