Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.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_Arrays_Linux_String_Unions - Fatal编程技术网

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