Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中字符串的字符指针_C_Function_Pointers_Parameters_Parameter Passing - Fatal编程技术网

C中字符串的字符指针

C中字符串的字符指针,c,function,pointers,parameters,parameter-passing,C,Function,Pointers,Parameters,Parameter Passing,因此,出于某种原因,当我调用GameGetCurretRomTitle()函数时,它无法正确打印roomData.title的内容,它会打印NULL。但是当我打印出函数本身内部的'title'变量时,它就工作了。。。我已经在完整的代码中包含了所有正确的文件、标题和所有语法都是正确的…C使用传递值传递函数参数。如果要从GameGetCurrentRoomTitle()函数更改roomData.title变量本身的值,则必须传递指向roomData.title的指针。然后,您可以使用strdup()

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

C
使用传递值传递函数参数。如果要从
GameGetCurrentRoomTitle()
函数更改
roomData.title
变量本身的值,则必须传递指向
roomData.title
的指针。然后,您可以使用
strdup()
gameData.title[0]
的内容复制到
GameGetCurrentRoomTitle()内部的
title
。您需要记住在之后释放指针

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


您需要相应地更改
GameGetCurrentRoomTitle()
函数。

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


您需要使用strcpy将标题复制到传递到函数中的缓冲区。不要只更改局部指针。

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

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);
}
以及它的号召

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

退出函数后,其局部变量标题将被销毁

如果要更改原始指针,必须传递其地址。在本例中,函数定义及其调用如下所示

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

假设
gameData.title
是指向
char
数组的指针数组

然后
gameData.title[0]
持有指向内存中“某处”存在的
char
数组的指针。假设标题是“Foobar”,这就是它在内存中的位置:

GameGetCurrentRoomTitle( &roomData.title );
//...
int GameGetCurrentRoomTitle( char **title ) {
    *title = &gameData.title[0];
    return strlen( *title );
}
假设标题前后的字节(或
char
s)在此时此刻未设置且未被程序使用,而上面的空槽就意味着这一点

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

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
指针p2-p4是
gameData.title
数组中
char
指针的其余部分

现在,在您的场景中还有两个有趣的指针。首先是
roomData.title
char
指针。为了简单起见,我们将其命名为
pA
。当您将其传递给
GameGetCurrentRoomTitle
时,它处于未设置状态,并指向内存空间中未定义的
char

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +-----------+
                         |
   [ ][ ][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]
其次是
GameGetCurrentRoomTitle
title
char
pointer参数。为了简单起见,我们称之为
pB
。当您将
pA
作为参数传递给
GameGetCurrentRoomTitle
时,其值将复制到
pB
。它的值不是它指向的内存的内容,而是它指向的地址。这意味着
pB
将指向内存空间中与
pA
相同的未定义
char

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +------------+
                          |
   [ ][pA][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]
       |
       +---------+
                 |
                 v
             [ ][ ][ ][ ]
接下来,在
GameGetCurrentRoomTitle
的主体中,您重新分配
pB
(本地标题
char
指针)以指向与
p1
相同的内存位置(指向
gameData.title[0]
中的
char
数组的指针):

而且,当
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][ ]
       |            
       +---------+
                 |
                 v
             [ ][ ][ ][ ]
通过将某些内容分配给被解除引用的
pB
,可以有效地分配给它所指向的内存位置,而不是
pB
本身。因此,在这种情况下,将
p1
分配给延迟的
pB
与将其分配给
pA
是相同的:

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +-------------+
                           |
   [ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
       ^            |
       |            |
       +------------+
在代码中:

[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
       +-----+-------------+
       |                   |
   [ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
[ ][ ][ ][ ][F][o][o][b][a][r][\0][ ][ ][ ][ ]
             ^
             |
             +-------------+
                           |
   [ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
       ^            |
       |            |
       +------------+
[ ][ ][ ][ ][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'
}