错误的实现(使用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
在作业中使用了两次。
答案 0 :(得分:3)
此实现无效,因为它包含未定义的行为。
解释来自标准第6.5节第2段:
在上一个和下一个sequence point之间,一个对象的表达式评估最多只能修改一次存储值。此外,先前的值应该是只读的,以确定要存储的值。
该标准给出了一个表达式的例子,该表达式被认为是未定义的行为以澄清第二句:
a[i++] = i;
在此表达式中,i
的值不仅用于确定要存储的新值,还用于确定另一个值的存储位置。
这正是你的表达中发生的事情:
*str++ = toupper(*str);
唯一的区别是你的表达式使用指针,并在其间调用toupper
。
这个要求似乎是随意的,但它有一个原因。 C标准允许编译器在++
调用之前或之后使toupper
的副作用可见,以使编译器编写者具有最大的灵活性。如果没有str
在表达式中使用的限制,这可能导致不同平台上的不同行为,因此标准作者决定完全禁止它。