我正在尝试学习C并希望使用union
。虽然我没有使用char *,但我看起来很顺利,但是我不会认为它会有所作为。
以下是我的工会宣布的方式:
union MyData
{
char * targetNumber;
int callResult;
} myData;
下面是我的主要功能,它使用我的联合并尝试存储然后从联合中读取
int main(int argc, char** argv)
{
union MyData myData;
asprintf(&myData.targetNumber, "My Target Number");
myData.callResult = 1;
printf("Target Number: %s\n", myData.targetNumber);
printf("Call Result: %i\n", myData.callResult);
return (EXIT_SUCCESS);
}
当我通过gdb它看起来像asprintf工作,但是当设置callResult时,targetNumber变得越界,所以当我尝试printf它时,它会段错误。我尝试使用strdup而不是asprintf,但没有喜悦。
感谢您提供的任何帮助。
答案 0 :(得分:3)
错误是您应该使用struct
而不是union
。您希望同时使用targetNumber
和callResult
,而不是其中任何一个,因此存储它们的正确数据结构是struct
。使用union
,它们存储在相同的内存位置。因此,写入一个会导致另一个的价值丢失。
此外,虽然不太可能,但asprintf()
可能会失败。您应该针对负值测试返回的int
。
注意:对于你用它做什么,asprintf(&myData.targetNumber, "My Target Number");
也可以写成myData.targetNumber = "My Target Number";
但我知道这可能是为了调试而减少的代码。
答案 1 :(得分:3)
我认为您混淆了union
和struct
之间的区别。如果您想将targetNumber
和callResult
分组到一个结构中,您可以执行以下操作:
struct MyData
{
char * targetNumber;
int callResult;
} myData;
然后你的代码应该可以工作。
当您将MyData
定义为union
时,您基本上创建的类型可以用作targetNumber
或callResult
,但不能同时用作两者,因为它们在记忆中占据相同的空间。
让我们假设sizeof(union MyData) == sizeof(targetNumber) == sizeof(int) == 4
,然后当您声明myData
时,myData
将被初始化为零(0x00000000
)。
union MyData myData; // 0x00000000
由于myData
归零,myData.targetNumber
也将归零,这也是NULL
指针。 asprintf()
将分配一个新字符串并填充其内容和
将其分配给myData.targetNumber
。通话结束后,myData.targetNumber
会指向内存中的某个位置(例如0x12345678
)。
asprintf(&myData.targetNumber, "My Target Number");
现在,您将myData.callResult
覆盖为1
(0x00000001
)。由于myData
是一个联合,因此会产生myData.callResult == myData.targentNumber == 1
。您刚刚丢失了指向已分配字符串的指针,因为myData.targetNumber
不再是0x12345678
而是0x00000001
。
myData.callResult = 1;
这将导致您的段错误。由于myData.targetNumber == 0x00000001
和0x00000001
不是有效指针(至少不是指向字符串的有效指针),因此可能会以段错误结束。
printf("Target Number: %s\n", myData.targetNumber);
如果你要到这里,myData.callResult
将正常打印。
printf("Call Result: %i\n", myData.callResult);
答案 2 :(得分:1)
union在内存中使用相同的空间。所以一旦你设置了callResult,targetNumber就变成了0x1。因此你丢失了你的字符串,而新的地址很低,应该导致seg错误。
UPDATE:union应该用于字节修改情况。在通用数据管理中,它没有struct那么有用。
答案 3 :(得分:0)
您不能将char *
用作字符数组。它只是一个变量来保存一个(或多个)字符的地址。
myData.callResult = 1
时,您正在覆盖(使其无法使用)存储在联合的myData.targetNumber
部分中的值(两个字段共享相同的存储空间)要为联盟分配数据,您必须使用以下内容:
union MyData {
char targetNumber[100]; /* allocate space for 100 characters */
int callResult; /* space for an integer is shared with the 100 characters of targetNumber */
} myData;
如果您想同时使用这两个字段,则无法共享相同的空间,而是需要struct
,如:
struct MyData {
char targetNumber[100]; /* allocate space for 100 characters */
int callResult; /* space for an integer is shared with the 100 characters of targetNumber */
} myData;
尝试在两种情况下都打印sizeof myData
,您将看到分配的存储资源的差异。 (第一个为联合中最长的字段分配空间,而第二个为两个字段分配空间)