C中字符串的Char指针

时间:2015-03-17 06:03:29

标签: c function pointers parameters parameter-passing

typedef struct {
    char *title;
    char *desc;
} RoomData;
RoomData roomData;
GameGetCurrentRoomTitle(roomData.title);

//INSIDE THE GAME.C FILE
int GameGetCurrentRoomTitle(char *title) {
    title = &gameData.title[0];
    return strlen(title);
}

因此,出于某种原因,当我调用GameGetCurretRoomTitle()函数时,它无法正确打印出roomData.title的内容,它会打印出NULL。但是当我打印出“标题”时函数本身内部的var工作...我已经包含了所有正确的文件,标题,并且所有语法在完整代码中都是正确的...

4 个答案:

答案 0 :(得分:1)

C使用pass-by-value进行函数参数传递。如果要从roomData.title函数更改GameGetCurrentRoomTitle()变量本身的,则必须将指针传递给roomData.title。然后,您可以使用strdup()gameData.title[0]的内容复制到title内的GameGetCurrentRoomTitle()。你需要记住以后释放指针。

否则,您可以将内存分配给title,然后再将其传递给GameGetCurrentRoomTitle(),然后在GameGetCurrentRoomTitle()内使用strcpy()gameData.title[0]复制字符串。< / p>

您需要累计更改GameGetCurrentRoomTitle()功能。

答案 1 :(得分:1)

函数的参数是其局部变量。您可以想象这个函数定义

int GameGetCurrentRoomTitle(char *title) {
    title = &gameData.title[0];
    return strlen(title);
}

及其电话

GameGetCurrentRoomTitle(roomData.title);

GameGetCurrentRoomTitle(roomData.title);
//...
int GameGetCurrentRoomTitle() {
    char *title = roomData.title;
    title = &gameData.title[0];
    return strlen(title);
}

退出该函数后,其本地变量标题将被销毁。

如果您希望更改原始指针,则必须传递其地址。在这种情况下,函数定义及其调用将类似于

GameGetCurrentRoomTitle( &roomData.title );
//...
int GameGetCurrentRoomTitle( char **title ) {
    *title = &gameData.title[0];
    return strlen( *title );
}

答案 2 :(得分:0)

在函数内设置变量的值不会改变调用者中变量的值。

您需要使用strcpy将标题复制到传递给函数的缓冲区中。不要只是改变本地指针。

答案 3 :(得分:0)

假设gameData.title是指向char数组

的指针数组

然后gameData.title[0]保存一个指向存储在“某处”的char数组的指针。让我们说标题是“Foobar”,这就是它在记忆中的位置:

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]

假设标题之前和之后的字节或char s在此时刻被程序取消设置并且未使用,并且上面的空插槽就意味着它。< / p>

现在,让我们调用指向char gameData.title[0] p1的{​​{1}}数组的指针。它指向“Foobar”char数组,如下所示:

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +-----------+
                         |
   [ ][ ][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]

指针p2-p4是char数组中gameData.title个指针的其余部分。

现在,您的场景中还有2个有趣的指针。首先,roomData.title char指针。为简单起见,我们称之为pA。当您将其传递给GameGetCurrentRoomTitle时,它会被取消设置并指向内存空间中未定义的char

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +------------+
                          |
   [ ][pA][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]
       |
       +---------+
                 |
                 v
             [ ][ ][ ][ ]

其次,GameGetCurrentRoomTitle标题char指针参数。为简单起见,我们称之为pB。将pA作为参数传递给GameGetCurrentRoomTitle时,其值将复制到pB。它的值不是它指向的内存的内容,而是它指向的地址。这意味着pB将指向内存空间中与char相同的未定义pA

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +-------------+
                           |
   [ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
       |            |
       +---------+--+
                 |
                 v
             [ ][ ][ ][ ]

接下来,在GameGetCurrentRoomTitle的正文中,您重新分配pB(本地标题char指针)以指向与p1相同的内存位置(指向char中的gameData.title[0]数组:

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +------+------+
                    |      |
   [ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
       |            
       +---------+
                 |
                 v
             [ ][ ][ ][ ]

并且,当GameGetCurrentRoomTitle最终返回其调用者时,pA仍然指向相同的未定义内存位置。

您错过的修复方法是将指针传递给pA而不是GameGetCurrentRoomTitle本身而不是pA本身,而不是重新分配pB要指向与p1相同的内存位置,您应该取消引用 pB并将p1分配给该内存位置,这是内存位置所在的内存位置存储pA变量。这样,当GameGetCurrentRoomTitle返回时,pA会看到您期望的字符串。

对于“图形”,新情况是pB不指向char数组,而指向指针指向char阵列。我们知道pA是指向char数组的指针:

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +-------------+
                           |
   [ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
       ^            |
       |            |
       +------------+

通过为解除引用的pB分配内容,您可以有效地分配它指向的内存位置,而不是pB本身。因此,将p1分配给引用的pB与在此方案中将其分配给pA相同:

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
       +-----+-------------+
       |                   |
   [ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]

在代码中:

GameGetCurrentRoomTitle(&roomData.title); // pass pointer to 'pA'

int GameGetCurrentRoomTitle(char **title) // 'pB' is a pointer to pointer
{ 
    *title = &gameData.title[0];         // assign 'p1' to dereferenced 'pB'
    return strlen(*title);               // measure dereferenced 'pB'
}