C 常量字符的strlen是否已优化?
我可以在这样的循环中使用C 常量字符的strlen是否已优化?,c,string,optimization,strlen,C,String,Optimization,Strlen,我可以在这样的循环中使用const char*的strlen,并期望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(常量字符*数据){ 对于(uint8_t i=0;i。不优化不考虑函数(甚至库)
const char*
的strlen
,并期望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(常量字符*数据){
对于(uint8_t i=0;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(),自己检测字符串的结尾。编译器可能会优化它,但可能不会达到您希望的程度。显然,这取决于编译器版本和优化级别
你可以考虑使用它来理解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\u 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);
那么
count
中的结果必须是2。如果编译器将strlen()
调用send_str()
从循环中提升出来,那么它将改为6-因此这不是编译器要进行的合法转换。即使strlen没有,编译器也应该对其进行优化。strlen(数据)是一个操作,将在每个循环中执行,最好使用一个变量来存储一次值并使用,因为如果使用GCC和Clang测试did soI,方法调用将发生一次;在每个回合中都调用<代码>斯特林< /代码>。不优化不考虑函数(甚至库)。是的,这实际上是XY问题…1用于关注OP的实际需求。在本例中,发送4个元素而不是1是否会改变性能?例如,检查地址是否可以被4整除,然后从4乘4开始,在发送之前查看数据的内容(如果有空的话)?另外,如果地址不能被4整除,先缓慢地执行1-3个元素,然后继续执行4乘4?-1,send\u byte()
只通过值传递一个字符,它不能修改任何内容。@unwind:send\u byte()
可以通过全局变量访问同一对象。