我可以在这样的循环中使用strlen
aconst char*
并期望 O(n) 时间复杂度,还是会导致 O(n^2)?我认为它看起来比使用字符串长度的变量更干净。
void send_str( const char* data ) {
for (uint8_t i = 0; i < strlen(data); i++)
send_byte( data[i] );
}
是否取决于优化级别?
我可以在这样的循环中使用strlen
aconst char*
并期望 O(n) 时间复杂度,还是会导致 O(n^2)?我认为它看起来比使用字符串长度的变量更干净。
void send_str( const char* data ) {
for (uint8_t i = 0; i < strlen(data); i++)
send_byte( data[i] );
}
是否取决于优化级别?
我认为你永远不能依赖优化的发生。
如果您真的想避免额外的变量,为什么不这样做:
void send_str(const char *data)
{
for(size_t i = strlen(data); i != 0; --i)
send_byte(*data++);
}
或者,不那么傻,更像是一个实际的生产质量 C 程序:
void send_str(const char *data)
{
while(*data != '\0')
send_byte(*data++);
}
对字符进行两次迭代根本没有意义,所以根本不要调用strlen()
,自己检测字符串的结尾。
编译器可能会优化它,但可能不会达到您想要的程度。显然取决于编译器版本和优化级别。
您可能会考虑使用MELT 探针来了解 GCC 对您的代码做了什么(例如,编译器将其转换为什么内部 Gimple 表示)。或者gcc -fverbose-asm -O -S
获取生成的汇编代码。
但是,对于您的示例,编码更简单:
void send_str(const char*data) {
for (const char*p = data; *p != 0; p++)
send_byte(*p);
}
如果在send_byte()
编译此代码时定义不可用(例如,它在另一个翻译单元中),那么这可能无法按照您描述的方式进行优化。这是因为const char *
指针不能保证指向的对象确实是const
,因此send_byte()
函数可以合法地修改它(send_byte()
可以通过全局变量访问该对象)。
例如,send_byte()
定义如下:
int count;
char str[10];
void send_byte(char c)
{
if (c == 'X')
str[2] = 0;
count++;
}
我们这样调用提供的send_str()
函数:
count = 0;
strcpy(str, "AXAXAX");
send_str(str);
那么结果 incount
必须是 2。如果编译器将strlen()
调用提升send_str()
到循环之外,那么它将改为 6 - 所以这不是编译器进行的合法转换。