1

嘿伙计们,

我一直在阅读一些关于指针和指针的东西,并开始感到好奇。我唯一不明白的是指针在函数中的行为,因此下面的代码:

#include <stdio.h>

int pointeeChanger(char* writeLocation) {

    writeLocation = "something";
    return 0;
}

int main(void)
{

    char crypted[] = "nothing";
    char* cryptedPointer = crypted;

    pointeeChanger(cryptedPointer);

    printf("The new value is: %s", cryptedPointer);

    return 0;
}

我的意图是通过给函数的指针来调整指针,“加密”var。唯一的问题是它不起作用。您能否解释一下我的思考过程中出了什么问题。我对C相当陌生,所以我的错误可能是相当基本的。

提前致谢!

问候,

基普特斯克里迪

4

4 回答 4

4

C 字符串不是学习指针的最佳材料,因为它们被实现为指向char. 让我们int改用:

#include <stdio.h>

void pointeeChanger(int* writeLocation) {
    // Using dereference operator "*"
    *writeLocation = 42; // something
}

int main(void) {
    int crypted = 0; // Nothing
    pointeeChanger(&cryptedPointer); // Taking an address with "&"
    printf("The new value is: %d", crypted);
    return 0;
}

这按预期工作。

就地修改字符串要困难得多,因为您被迫处理内存管理问题。具体来说,您复制到的字符串必须分配足够的空间以容纳新字符串。这不适用于“nothing”和“something”,因为替换要长两个字符。

于 2013-02-12T01:45:11.687 回答
3

简短的回答:writeLocation是一个局部变量,是cryptedPointer. 修改writeLocation时,cryptedPointer不修改。

如果要修改cryptedPointer,则必须将指针传递给它,如下所示:

#include <stdio.h>

int pointeeChanger(char** writeLocation) {            /* Note: char** */

    *writeLocation = "something";                     /* Note: *writeLocation */
    return 0;
}

int main(void)
{

    char crypted[] = "nothing";
    char* cryptedPointer = crypted;

    pointeeChanger(&cryptedPointer);                  /* Note: &cryptedPointer */

    printf("The new value is: %s", cryptedPointer);

    return 0;
}

但是,此代码还有其他问题。调用后pointeeChanger()cryptedPointer不再指向crypted数组。我怀疑您实际上想更改该数组的内容。此代码无法做到这一点。

要更改您的值,crypted[]您需要使用strcpy()or (preferably) strncpy()。此外,您将需要注意crypted[]数组的大小 -"something"长度大于"nothing"并将导致缓冲区溢出,除非crypted[]将其做得更大。

此代码将修改原始crypted[]数组:

#include <stdio.h>
#include <string.h>

#define MAX_STR_LEN 64

/*
 * Only char* required because we are not modifying the
 * original pointer passed in - we are modifying what it
 * points to.
 */
int pointeeChanger(char* writeLocation)
{
    /*
     * In C, you need to use a function like strcpy or strncpy to overwrite a
     * string with another string. Prefer strncpy because it allows you to
     * specify a maximum size to copy, which helps to prevent buffer overruns.
     */
    strncpy(writeLocation, "something", MAX_STR_LEN);

    /* strncpy doesn't automatically add a \0 */
    writeLocation[MAX_STR_LEN] = '\0';

    return 0;
}


int main(void)
{
    /*
     * The +1 is because an extra character is required for the 
     * null terminator ('\0')
     */
    char crypted[MAX_STR_LEN + 1] = "nothing";

    pointeeChanger(crypted);

    printf("The new value is: %s", crypted);

    return 0;

}
于 2013-02-12T01:39:39.087 回答
2

这取决于您实际想要做什么:

您要更改cryptedPointer指向的内容,还是更改cryptedPointer指向的内容?

第二个可以通过以下方式完成:

  strcpy(writeLocation, "something"); 

请注意,如果something长于原始字符串的大小,则会溢出缓冲区,这是一件坏事。所以要解决这个问题,你必须有char crypted[10] = "nothing";, 为字符串“something”腾出空间。

您显然也可以执行以下操作:

 writeLocation[2] = 'f';
 writeLocation[3] = 'f';

printf打印“noffing”

但是如果你想做第一个变体,那么你需要将一个指针传递给指针:

int pointeeChanger(char** writeLocation) {

    *writeLocation = "something";
    return 0;
}

然后调用:

pointeeChanger(&cryptedPointer); 

请注意,当它返回时,cruptedPointer它指向一个无法修改的常量字符串,您的原始字符串可以在其中crypted进行修改。

于 2013-02-12T01:45:06.623 回答
1

想想汤姆受雇于莎莉为黑手党打破指关节。

按值传递:如果 Sally 让 Tom 数数他今天在工作中折断的指节数,那么 Sally 无法知道 Tom 计算出的数字是多少,直到他从路上回来。一开始他们的脑海中都有一个数字“零”的副本,但汤姆的数字可能会在一天中增加。

请注意“复制”一词。当您将值传递给函数时,您传递的是对象的副本。当您在函数中修改对象时,您修改的是副本而不是原始对象。

Pass-by-reference:如果 Sally 告诉 Tom 计算他在天空中折断的指节数,那么她(以及任何其他感兴趣的人)可以参考天空。通过改变天空,汤姆也将改变莎莉的号码。

编辑:C 没有按引用传递,尽管它确实有指针,它们是引用类型。传递指针仍然是按值传递,仍然形成具有相同指针值的副本。因此,您的任务是副本,而不是原件。

于 2013-02-12T02:40:50.840 回答