简体   繁体   English

我错过了指针吗?

[英]Have I missed the point of pointers?

OK, sorry about the bad pun :P 对不好的双关语抱歉:P

I've coded the old trick of HAL => IBM in C. I've just read the first few pages in K&R reguarding them, and I thought it would be a good first play with them. 我在C中编写HAL => IBM的旧技巧。我刚读完了K&R中的前几页,我认为这对他们来说是一个很好的第一次。

char evil[] = "HAL";
char *ptr = evil;   
for (int i = 0; i < strlen(evil); ++i, ++ptr) {             
    (*ptr)++;           
}   
printf("%s\n", evil); // IBM

My problem is, I have two variables incrementing, i and ptr , and something is telling me one of them is redundant (perhaps I'm still not thinking C well enough). 我的问题是,我有两个变量递增, iptr ,有些东西告诉我其中一个是多余的(也许我还没有考虑 C足够好)。

The only reason I use i is to determine if we have read to the end of the string. 我使用i的唯一原因是确定我们是否已读到字符串的末尾。 Is there any way to check the pointer to see if it has arrived at the end of the string? 有没有办法检查指针,看它是否已到达字符串的末尾?

Update 更新

Sorry for any confusion of the actual question. 对不起任何实际问题的混淆。 By have I missed the point I basically meant, why would I use a pointer when I needed an incrementing index to check the length as well. 我错过了我基本上意味着什么,当我需要一个递增索引来检查长度时,为什么我会使用指针。 I could just use that index to subscript the right char from the array. 我可以使用该索引从数组中下标右边的char。

你也可以写

for (char *ptr = evil; *ptr != '\0' ; ++ptr)

I typed the question, re-read it, and then realised something very obvious I had overlooked! 我输入了问题,重新阅读,然后意识到我忽略了一些非常明显的事情!

char evil[] = "HAL" 
char *ptr = evil;   
for (; *ptr != '\0'; ++ptr) {                       
    (*ptr)++;           
}   
printf("%s\n", evil);

That seemed to do the trick. 这似乎成功了。

You've figured out the correct implementation, but I would still like to make one point about your original code, which may give you a different way to think about such problems. 您已经找到了正确的实现,但我仍然想对您的原始代码提出一点意见,这可能会让您以不同的方式思考这些问题。

Your original solution may be even worse than you think, because its complexity is actually O(n^2), where n is the length of the string. 您的原始解决方案可能比您想象的更糟糕,因为它的复杂性实际上是O(n ^ 2),其中n是字符串的长度。 strlen() has a complexity of O(n), because it has to iterate over all the characters in the string until it finds '\\0' . strlen()的复杂度为O(n),因为它必须迭代字符串中的所有字符,直到找到'\\0' So you have a loop that performs n iterations, and calls strlen() each time, resulting in the complexity of O(n^2). 所以你有一个执行n次迭代的循环,每次调用strlen() ,导致O(n ^ 2)的复杂性。

At the very least you should call strlen() once before the loop, and cache the length of the string. 至少你应该在循环之前调用strlen()一次,并缓存字符串的长度。 And, of course, you have the correct solution that does not call strlen() at all. 当然,你有正确的解决方案,根本不会调用strlen()

In C strings end with '\\0' . C字符串中以'\\0'结尾。 You can use that fact to stop the loop. 您可以使用该事实来停止循环。

for (; *ptr != '\0' ; ++ptr) {
    /* ... */
}

The character pointed to will be '\\0' . 指向的字符将是'\\0' But be careful, misplacing the NUL byte can be a source of program crashes or security holes. 但要小心,错放NUL字节可能是程序崩溃或安全​​漏洞的来源。

Calling strlen(evil) is inefficient. 调用strlen(evil)是低效的。 Instead of relying on strlen , use the same thing that makes strlen stop: the null terminator: 而不是依赖strlen ,使用使strlen停止的相同的东西:null终止符:

for (char *ptr = evil; *ptr; ++ptr) {             
    (*ptr)++;           
}

This would do the trick: 这样可以解决问题:

char evil[] = "HAL";
*(int*) evil += 65793;
printf("%s\n", evil);

Since we are talking about evil: 既然我们在谈论邪恶:

#include <stdio.h>

int main()
{
    char evil[] = "HAL";
    char *ptr;

    // Increment the pointer and its content in the same expression
    // Just to be really evil

    for (ptr = evil; *ptr != '\0'; ++*(ptr++)) { }

    printf("%s\n", evil);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM