C中变量中需要的垃圾值
我试图将两个无符号字符数组元素存储到字符串变量中。其中一个变量将包含垃圾字符,当我尝试存储垃圾字符时,垃圾字符无法与有效值一起存储 这是我的密码C中变量中需要的垃圾值,c,arrays,linux,string,unions,C,Arrays,Linux,String,Unions,我试图将两个无符号字符数组元素存储到字符串变量中。其中一个变量将包含垃圾字符,当我尝试存储垃圾字符时,垃圾字符无法与有效值一起存储 这是我的密码 union u_type { unsigned int IntVar; unsigned char Bytes[2]; } temp; void main(void) { temp.IntVar = 39; printf("%c%c",temp.Bytes[1],temp.Bytes[0]); } 当我运行此代码
union u_type
{
unsigned int IntVar;
unsigned char Bytes[2];
} temp;
void main(void)
{
temp.IntVar = 39;
printf("%c%c",temp.Bytes[1],temp.Bytes[0]);
}
当我运行此代码时,cc test.c
和/a.out>tempfile
现在,tempfile包含以下内容
^@
我明白
临时字节[1]
是^@
和临时字节[0]
是'
我想将两个数组元素合并成一个字符串,该字符串应包含^@'
。我试过下面的方法
printf("%c%c",temp.Bytes[1],temp.Bytes[0]);
memcpy(string, &temp.Bytes[1],1);
memcpy(string,&temp.Bytes[0],1);
printf("%s",str);
现在str只包含
”
,但我想像这样将^@'
存储到字符串变量中。您的memcpy的问题有2个:
您总是将项目复制到同一地址:string
变量的第一个字节
结果字符串可能不是以null结尾的。我写这篇文章可能是因为我不知道string
是如何定义的
第三件事我认为您缺少大小为int
type的内容:
试试这个
union u_type
{
unsigned int IntVar;
unsigned char Bytes[sizeof(int)];
}temp;
int main(void)
{
size_t i;
temp.IntVar = 39;
printf("Size of int: %zu\n", sizeof(int));
for (i=1; i<sizeof(int)+1; i++)
printf("%02X ",temp.Bytes[sizeof(int)-i]);
printf("\n");
return 0;
}
因此,您应该使用c字符串标准函数来完成您的工作:即sprintf
:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
union u_type
{
unsigned int IntVar;
unsigned char Bytes[sizeof(int)];
}temp;
int main(void)
{
size_t i;
char string[(sizeof(int)*2)+1] = {0};
uint8_t index = 0;
temp.IntVar = 39;
for (i=1; i<sizeof(int)+1; i++)
{
index += sprintf(&string[index], "%02X", temp.Bytes[sizeof(int)-i]);
}
printf(string);
printf("\n");
return 0;
}
请注意,我所有的代码都没有考虑endianness。
您可以使用一个简单的函数来完成此操作,如下所示:
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
union u_type
{
unsigned int IntVar;
unsigned char Bytes[sizeof(int)];
}temp;
bool is_big_endian ( void )
{
unsigned int x = 1;
char *c = (char*) &x;
return (bool)*c;
}
int main(void)
{
size_t i;
char string[(sizeof(int)*2)+1] = {0};
uint8_t index = 0;
temp.IntVar = 0x12345678;
printf("%zu\n", sizeof(int));
if (is_big_endian())
{
for (i=1; i<sizeof(int)+1; i++)
{
index += sprintf(&string[index], "%02X", temp.Bytes[sizeof(int)-i]);
}
}
else
{
for (i=0; i<sizeof(int); i++)
{
index += sprintf(&string[index], "%02X", temp.Bytes[i]);
}
}
printf(string);
printf("\n");
return 0;
}
#包括
#包括
#包括
#包括
联合u型
{
无符号int-int-var;
无符号字符字节[sizeof(int)];
}温度;
布尔是大的(空的)
{
无符号整数x=1;
char*c=(char*)&x;
返回(bool)*c;
}
内部主(空)
{
尺寸i;
字符字符串[(sizeof(int)*2)+1]={0};
uint8_t指数=0;
temp.IntVar=0x12345678;
printf(“%zu\n”,sizeof(int));
如果(是大的吗?)
{
for(i=1;i^@
是一些C函数打印空字符('\0'
)的方式。但该字符也被视为字符串的结尾。因此它通常不会出现在printf(“%s”)
的输出中。该字符在那里(所有普通C字符串的结尾都有一个字符)但是你必须做一些特殊的事情来打印它。与结构不同,当你定义联合时,所有的联合成员都是在同一个内存地址创建的,并且将根据成员类型
至少共享为联合分配的相同内存空间的一部分分配给其中一个成员时,其值将放置在内存中的该位置,使用该成员的数据类型
的适当字节数。如果您随后分配给另一个成员,可能是不同的类型
,它将把新值放置在同一位置,可能会销毁部分或全部这是联合的正常行为。您不能相信在后续赋值时,任何先前的赋值仍然有效。因此,在写入另一个成员后读取联合
成员的值在C中是未定义的行为
复制场景时,您将创建一个联合:
union u_type
{
unsigned int IntVar;
unsigned char Bytes[2];
} temp;
uint需要4个字节,uchar数组需要2个:
0 1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
第一次赋值时,temp.IntVar=39
用值39填充内存:
0 1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031
|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|1|1|1| //decimal 39
在我的环境中,复制此场景时,两个成员都位于内存位置0x0040AA30。查看uint成员时,temp.IntVar
,我看到:
当我查看uchar成员时,temp.Bytes
,我看到:
这正好等于在ASCII中查看时的值39
。因为我的内存查看器根据查看的成员类型选择默认的查看格式,所以它选择ASCII作为第二个图像,以显示uchar。当我强制它在long int
中查看内存时,它会变回:
因此,这一切实际上归结为识别什么样的上下文(或什么格式)您是否正在查看同一内存位置的内容,并且应始终在仅查看最新分配的成员时解释该上下文。您不能期望单位化变量在每次执行中具有相同的值。当您再次运行程序时,字节[0]和字节[1]可能有完全不同的值。此外,当您第二次调用字符串时,memcpy将覆盖该字符串的内容。如果您希望向字符串添加两个字符,则应执行类似以下操作:字符串[0]=字节[0];字符串[1]=字节[1]为完整起见,您希望向我们展示如何定义和初始化str
。对memcpy()
的两个调用将每个字节复制到完全相同的地址。此外,请三思而后行,您希望通过复制两个字节来接收由三个字符(“^@'
)组成的结果。这应该如何工作?这里有些不适合。。。“可能结果字符串不是空终止符。”最有可能的是,甚至比预期的“更多”,因为^@
可能是'\0'
!:-)@alk我打赌:),但可能是bss
或calloc
-ated或zero-inited;)谁知道呢……因为第二个memcpy()
覆盖NUL
。如果是,则printf()
将不打印任何内容。
0 1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
0 1 2 3 4 5 6 7 8 9 10111213141516171819202122232425262728293031
|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|1|1|1| //decimal 39