2

我可以在这样的循环中使用strlenaconst 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] );
}

是否取决于优化级别?

4

3 回答 3

18

我认为你永远不能依赖优化的发生。

如果您真的想避免额外的变量,为什么不这样做:

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(),自己检测字符串的结尾。

于 2013-07-09T10:13:42.890 回答
0

编译器可能会优化它,但可能不会达到您想要的程度。显然取决于编译器版本和优化级别。

您可能会考虑使用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);
 }
于 2013-07-09T10:15:17.177 回答
0

如果在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 - 所以这不是编译器进行的合法转换。

于 2013-07-09T11:42:42.513 回答