C中变量所需的垃圾值

时间:2016-05-27 13:52:35

标签: 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]);
}

当我运行此代码cc test.c./a.out > tempfile时 现在临时文件包含以下内容

  

^@'

我理解

temp.Bytes[1]^@temp.Bytes[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仅包含'但是,我希望将此^@'存储到字符串变量中。

3 个答案:

答案 0 :(得分:3)

^@是一些C函数打印空字符('\0')的方式。但是该字符也被视为字符串的结尾。因此它通常不会出现在printf("%s")的输出中。角色是那里(所有正常的C字符串最后都有一个),但你必须做一些特别的事情来打印它。

答案 1 :(得分:0)

select id, count(case when inc_or_dec = 'increase' then 1 end) increases, count(case when inc_or_dec = 'decrease' then 1 end) decreases from ( select id, case when coalesce(lead(value1) over(partition by id order by mth),value1) > value1 then 'increase' when coalesce(lead(value1) over(partition by id order by mth),value1) < value1 then 'decrease' when coalesce(lead(value1) over(partition by id order by mth),value1) = value1 then 'no change' end inc_or_dec from tablename) t group by id 的问题是2:

  1. 您总是将项目复制到同一地址:memcpy变量的第一个字节
  2. 结果字符串可能不是以空值终止的。我正在写可能是因为我不知道如何定义string
  3. 第三件事我认为你错过了string类型的小东西:

    试试这个

    int

    输出

    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-string标准函数来完成你的工作:即4 00 00 00 27

    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;
    }
    

    请注意,我的所有代码都没有处理字节序。 你可以使用一个简单的函数来做到这一点:

    00000027
    

答案 2 :(得分:0)

struct不同,当您定义union时,所有union members都是在同一个内存地址创建的,并且会根据成员type < em> share 至少为联合分配的相同内存空间的一部分。当您对其中一个成员进行赋值时,它的值将放在内存中的该位置,使用该成员的数据type的适当字节数。如果您对另一个成员(可能是另一个成员type)进行后续分配,则会将新值放在同一位置,可能会破坏部分或之前的所有值。这是联盟的正常行为。您无法相信,在后续作业中,任何先前的作业仍然可行。因此,在写入另一个成员之后读取union成员的值是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时,我看到: enter image description here

当我查看uchar成员temp.Bytes时,我看到: enter image description here

在ASCII中查看时,它恰好等于值39。因为我的内存查看器根据正在查看的成员类型选择默认查看格式,所以它为第二个图像选择了ASCII,以显示uchar。当我强制它查看long int中的内存时,它会变回: enter image description here

所有这一切都归结为识别使用什么上下文(或什么格式)查看相同内存位置的内容,并且应始终在查看 最新分配的内容时解释该上下文会员。