C strlen使用指针
我见过使用指针的strlen的标准实现:C strlen使用指针,c,C,我见过使用指针的strlen的标准实现: int strlen(char * s) { char *p = s; while (*p!='\0') p++; return p-s; } 我知道这是可行的,但当我尝试用另外3种方法(现在就学习指针算术)来做这件事时,我想知道它们有什么问题 这与这本书的内容有些相似。这是错的吗 int strlen(char * s) { char *p = s; while (*p) p++; return p-s; }
int strlen(char * s) {
char *p = s;
while (*p!='\0')
p++;
return p-s;
}
我知道这是可行的,但当我尝试用另外3种方法(现在就学习指针算术)来做这件事时,我想知道它们有什么问题
int strlen(char * s) {
char *p = s;
while (*p)
p++;
return p-s;
}
int strlen(char * s) {
char *p = s;
while (*p++)
;
return p-s;
}
p
与空指针进行比较
2) 程序运行时,称为堆栈的内存区域未初始化。局部变量存在于此。您编写程序的方式将p
放入堆栈中(如果您将其设置为const
或使用malloc
,它几乎肯定会存在于其他地方)。当你看*p
时,你会看到堆栈。如果字符串长度为0,则与charp[1]={0}
相同。预递增查找紧跟在\0
之后的字节,因此您查找的是未定义的内存。这里有龙
3) 我认为这里没有问题:)正如你所看到的,它总是比正确答案多返回一个
附录:如果您喜欢这种样式,也可以使用for循环编写:
size_t strlen(char * s) {
char *p = s;
for (; *p != '\0'; p++) {}
return p - s;
}
或者(更容易出错)
此外,strlen不能返回负数,因此应该使用无符号值<代码>大小\u t更好。1)在我看来很好。我个人更喜欢对“\0”进行显式比较,这样就可以清楚地看出,在上下文不清楚的情况下,您并不打算(例如)将p
与空指针进行比较
2) 程序运行时,称为堆栈的内存区域未初始化。局部变量存在于此。您编写程序的方式将p
放入堆栈中(如果您将其设置为const
或使用malloc
,它几乎肯定会存在于其他地方)。当你看*p
时,你会看到堆栈。如果字符串长度为0,则与charp[1]={0}
相同。预递增查找紧跟在\0
之后的字节,因此您查找的是未定义的内存。这里有龙
3) 我认为这里没有问题:)正如你所看到的,它总是比正确答案多返回一个
附录:如果您喜欢这种样式,也可以使用for循环编写:
size_t strlen(char * s) {
char *p = s;
for (; *p != '\0'; p++) {}
return p - s;
}
或者(更容易出错)
此外,strlen不能返回负数,因此应该使用无符号值<代码>大小\u t甚至更好。版本1很好-
而(*p!='\0')
相当于而(*p!=0)
,相当于而(*p)
在原始代码和版本1中,指针p
当且仅当*p
不是0
(注意,您不在字符串的末尾)时才是高级的
无论
*p
是否为0
,第2版和第3版都将升级p
*p++
计算为p
所指向的字符,并作为副作用前进p
*++p
计算为p
所指向的字符后面的字符,并作为副作用前进p
。因此,版本2和版本3将始终前进p
超过字符串的末尾,这就是您的值关闭的原因 版本1很好-while(*p!='\0')
相当于while(*p!=0)
,这相当于while(*p)
在原始代码和版本1中,指针p
当且仅当*p
不是0
(注意,您不在字符串的末尾)时才是高级的
无论
*p
是否为0
,第2版和第3版都将升级p
*p++
计算为p
所指向的字符,并作为副作用前进p
*++p
计算为p
所指向的字符后面的字符,并作为副作用前进p
。因此,版本2和版本3将始终前进p
超过字符串的末尾,这就是您的值关闭的原因 当您比较strlen
替换函数的性能时,会遇到的一个问题是,与长字符串的实际strlen
函数相比,它们的性能会受到影响?为什么?strlen
在搜索字符串结尾时,每次迭代处理超过一个字节。如何实现更高效的替换
没那么难。基本方法是每次迭代查看4字节,并根据在这4字节中找到nul字节的位置调整返回。您可以执行以下操作(使用数组索引):
您可以使用指针和掩码执行完全相同的操作:
size_t strsz (const char *s) {
size_t len = 0;
for(;;) {
unsigned x = *(unsigned*)s;
if((x & 0xff) == 0) return len;
if((x & 0xff00) == 0) return len + 1;
if((x & 0xff0000) == 0) return len + 2;
if((x & 0xff000000) == 0) return len + 3;
s += 4, len += 4;
}
}
无论哪种方式,您都会发现每次迭代都会进行4字节的比较,其性能相当于strlen本身。当您比较strlen替换函数的性能时,您会遇到一个问题:与长字符串的实际strlen函数相比,它们的性能会受到影响吗?为什么?
strlen
在搜索字符串结尾时,每次迭代处理超过一个字节。如何实现更高效的替换
没那么难。基本方法是每次迭代查看4字节,并根据在这4字节中找到nul字节的位置调整返回。您可以执行以下操作(使用数组索引):
你能行
size_t strsz_idx (const char *s) {
size_t len = 0;
for(;;) {
if (s[0] == 0) return len;
if (s[1] == 0) return len + 1;
if (s[2] == 0) return len + 2;
if (s[3] == 0) return len + 3;
s += 4, len += 4;
}
}
size_t strsz (const char *s) {
size_t len = 0;
for(;;) {
unsigned x = *(unsigned*)s;
if((x & 0xff) == 0) return len;
if((x & 0xff00) == 0) return len + 1;
if((x & 0xff0000) == 0) return len + 2;
if((x & 0xff000000) == 0) return len + 3;
s += 4, len += 4;
}
}