C 中指向 String 的 Char 指针
Char pointer to String in C
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。但是当我打印出函数本身内部的 'title' var 时,它起作用了……我已经包含了所有正确的文件,headers,并且所有语法在完整代码中都是正确的……
C
使用按值传递函数参数传递。如果要从 GameGetCurrentRoomTitle()
函数更改 roomData.title
变量本身的 value,则必须传递指向 roomData.title
的指针。然后可以用strdup()
把gameData.title[0]
的内容复制到GameGetCurrentRoomTitle()
里面的title
。你需要记住之后释放指针。
否则,您可以先将内存分配给 title
,然后再将其传递给 GameGetCurrentRoomTitle()
,然后在 GameGetCurrentRoomTitle()
中使用 strcpy()
从 gameData.title[0]
复制字符串.
您需要相应地更改 GameGetCurrentRoomTitle()
函数。
在函数内部设置变量值不会改变调用方变量的值。
您需要使用 strcpy 将标题复制到传递给函数的缓冲区中。不要只改变本地指针。
函数的参数是它的局部变量。你可以想象这个函数定义
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);
}
函数退出后其局部变量title会被销毁
如果您希望更改原始指针,则必须传递其地址。在这种情况下,函数定义及其调用将类似于
GameGetCurrentRoomTitle( &roomData.title );
//...
int GameGetCurrentRoomTitle( char **title ) {
*title = &gameData.title[0];
return strlen( *title );
}
假设 gameData.title
是指向 char
数组的指针数组
然后 gameData.title[0]
持有一个指向内存中存在 "somewhere" 的 char
数组的指针。假设标题是 "Foobar",这是它在内存中的位置:
[ ][ ][ ][ ][F][o][o][b][a][r][[=10=]][ ][ ][ ][ ]
假设紧接标题前后的字节或 char
s 在此时刻未被程序设置和未使用,并且上面的空槽意味着.
现在,让我们为 p1
调用 gameData.title[0]
中的 char
数组的指针。它指向 "Foobar" char
数组,像这样:
[ ][ ][ ][ ][F][o][o][b][a][r][[=11=]][ ][ ][ ][ ]
^
|
+-----------+
|
[ ][ ][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]
指针 p2-p4 是 gameData.title
数组中其余 char
个指针。
现在,您的场景中有 2 个更有趣的提示。首先,roomData.title
char
指针。为简单起见,我们称它为 pA
。当您将它传递给 GameGetCurrentRoomTitle
时,它未设置并指向内存中未定义的 char
space:
[ ][ ][ ][ ][F][o][o][b][a][r][[=12=]][ ][ ][ ][ ]
^
|
+------------+
|
[ ][pA][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]
|
+---------+
|
v
[ ][ ][ ][ ]
二、GameGetCurrentRoomTitle
标题char
指针参数。为简单起见,我们将其称为 pB
。当您将 pA
作为参数传递给 GameGetCurrentRoomTitle
时,它的值将被复制到 pB
。它的值不是它指向的内存的内容,而是它指向的地址。这意味着 pB
将指向内存 space 中与 pA
相同的未定义 char
:
[ ][ ][ ][ ][F][o][o][b][a][r][[=13=]][ ][ ][ ][ ]
^
|
+-------------+
|
[ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
| |
+---------+--+
|
v
[ ][ ][ ][ ]
接下来,在 GameGetCurrentRoomTitle
的 body 中,您重新分配 pB
(本地标题 char
指针)以指向与 [=25] 相同的内存位置=](指向 gameData.title[0]
中的 char
数组的指针):
[ ][ ][ ][ ][F][o][o][b][a][r][[=14=]][ ][ ][ ][ ]
^
|
+------+------+
| |
[ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
|
+---------+
|
v
[ ][ ][ ][ ]
并且,当 GameGetCurrentRoomTitle
最终 returns 到它的调用者时,pA
仍然指向同一个未定义的内存位置。
您错过的解决方法是将 指针 传递给 pA
再传递给 GameGetCurrentRoomTitle
而不是 pA
本身,而不是重新分配pB
要指向与 p1
相同的内存位置,您应该 取消引用 pB
并将 p1
分配给该内存位置,这是存储 pA
变量值的内存位置。这样,当 GameGetCurrentRoomTitle
returns 时,pA
将看到您期望的字符串。
对于 "graphics",新的情况是 pB
不指向 char
数组,而是指向 指针 到 char
数组。我们知道 pA
是指向 char
数组的指针:
[ ][ ][ ][ ][F][o][o][b][a][r][[=15=]][ ][ ][ ][ ]
^
|
+-------------+
|
[ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
^ |
| |
+------------+
通过将某些内容分配给取消引用的 pB
,您可以有效地分配给它指向的内存位置,而不是分配给 pB
本身。因此,在这种情况下,将 p1
分配给被引用的 pB
与将其分配给 pA
相同:
[ ][ ][ ][ ][F][o][o][b][a][r][[=16=]][ ][ ][ ][ ]
^
|
+-----+-------------+
| |
[ ][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'
}
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。但是当我打印出函数本身内部的 'title' var 时,它起作用了……我已经包含了所有正确的文件,headers,并且所有语法在完整代码中都是正确的……
C
使用按值传递函数参数传递。如果要从 GameGetCurrentRoomTitle()
函数更改 roomData.title
变量本身的 value,则必须传递指向 roomData.title
的指针。然后可以用strdup()
把gameData.title[0]
的内容复制到GameGetCurrentRoomTitle()
里面的title
。你需要记住之后释放指针。
否则,您可以先将内存分配给 title
,然后再将其传递给 GameGetCurrentRoomTitle()
,然后在 GameGetCurrentRoomTitle()
中使用 strcpy()
从 gameData.title[0]
复制字符串.
您需要相应地更改 GameGetCurrentRoomTitle()
函数。
在函数内部设置变量值不会改变调用方变量的值。
您需要使用 strcpy 将标题复制到传递给函数的缓冲区中。不要只改变本地指针。
函数的参数是它的局部变量。你可以想象这个函数定义
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);
}
函数退出后其局部变量title会被销毁
如果您希望更改原始指针,则必须传递其地址。在这种情况下,函数定义及其调用将类似于
GameGetCurrentRoomTitle( &roomData.title );
//...
int GameGetCurrentRoomTitle( char **title ) {
*title = &gameData.title[0];
return strlen( *title );
}
假设 gameData.title
是指向 char
数组的指针数组
然后 gameData.title[0]
持有一个指向内存中存在 "somewhere" 的 char
数组的指针。假设标题是 "Foobar",这是它在内存中的位置:
[ ][ ][ ][ ][F][o][o][b][a][r][[=10=]][ ][ ][ ][ ]
假设紧接标题前后的字节或 char
s 在此时刻未被程序设置和未使用,并且上面的空槽意味着.
现在,让我们为 p1
调用 gameData.title[0]
中的 char
数组的指针。它指向 "Foobar" char
数组,像这样:
[ ][ ][ ][ ][F][o][o][b][a][r][[=11=]][ ][ ][ ][ ]
^
|
+-----------+
|
[ ][ ][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]
指针 p2-p4 是 gameData.title
数组中其余 char
个指针。
现在,您的场景中有 2 个更有趣的提示。首先,roomData.title
char
指针。为简单起见,我们称它为 pA
。当您将它传递给 GameGetCurrentRoomTitle
时,它未设置并指向内存中未定义的 char
space:
[ ][ ][ ][ ][F][o][o][b][a][r][[=12=]][ ][ ][ ][ ]
^
|
+------------+
|
[ ][pA][ ][ ][ ][ ][ ][p1][p2][p3][p4][ ]
|
+---------+
|
v
[ ][ ][ ][ ]
二、GameGetCurrentRoomTitle
标题char
指针参数。为简单起见,我们将其称为 pB
。当您将 pA
作为参数传递给 GameGetCurrentRoomTitle
时,它的值将被复制到 pB
。它的值不是它指向的内存的内容,而是它指向的地址。这意味着 pB
将指向内存 space 中与 pA
相同的未定义 char
:
[ ][ ][ ][ ][F][o][o][b][a][r][[=13=]][ ][ ][ ][ ]
^
|
+-------------+
|
[ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
| |
+---------+--+
|
v
[ ][ ][ ][ ]
接下来,在 GameGetCurrentRoomTitle
的 body 中,您重新分配 pB
(本地标题 char
指针)以指向与 [=25] 相同的内存位置=](指向 gameData.title[0]
中的 char
数组的指针):
[ ][ ][ ][ ][F][o][o][b][a][r][[=14=]][ ][ ][ ][ ]
^
|
+------+------+
| |
[ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
|
+---------+
|
v
[ ][ ][ ][ ]
并且,当 GameGetCurrentRoomTitle
最终 returns 到它的调用者时,pA
仍然指向同一个未定义的内存位置。
您错过的解决方法是将 指针 传递给 pA
再传递给 GameGetCurrentRoomTitle
而不是 pA
本身,而不是重新分配pB
要指向与 p1
相同的内存位置,您应该 取消引用 pB
并将 p1
分配给该内存位置,这是存储 pA
变量值的内存位置。这样,当 GameGetCurrentRoomTitle
returns 时,pA
将看到您期望的字符串。
对于 "graphics",新的情况是 pB
不指向 char
数组,而是指向 指针 到 char
数组。我们知道 pA
是指向 char
数组的指针:
[ ][ ][ ][ ][F][o][o][b][a][r][[=15=]][ ][ ][ ][ ]
^
|
+-------------+
|
[ ][pA][ ][ ][ ][pB][ ][p1][p2][p3][p4][ ]
^ |
| |
+------------+
通过将某些内容分配给取消引用的 pB
,您可以有效地分配给它指向的内存位置,而不是分配给 pB
本身。因此,在这种情况下,将 p1
分配给被引用的 pB
与将其分配给 pA
相同:
[ ][ ][ ][ ][F][o][o][b][a][r][[=16=]][ ][ ][ ][ ]
^
|
+-----+-------------+
| |
[ ][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'
}