printf%我是如何在这种情况下工作的?

时间:2018-06-12 16:54:09

标签: c arrays struct printf

很抱歉尝试以另一种方式询问此question

typedef   struct 
 { 
    char duo_word[8]; 
 } duo_word;


  duo_word duo_word_inst = { .duo_word = { 'º', '\b', '\x1', '\0', 'À', '\xe', '2', 'a' } };

  printf("          %i ", duo_word_inst); // gives 67770 but how?

如何将67770值提取到例如一个int变量?

3 个答案:

答案 0 :(得分:3)

%i的{​​{1}}格式说明符需要printf作为参数。但是,您传递的是int。使用错误的duo_word格式说明符调用undefined behavior。在这种情况下,你很幸运"它碰巧打印出你想要的东西,但你不能依赖这种行为。

假设struct中的前4个字节表示小端格式的32位整数,则可以拉出各个字节并将它们设置为整数,如下所示:

printf

答案 1 :(得分:1)

这是未定义的行为,所以任何事情都可能发生。

可能发生的事情是duo_word_inst只会粘贴在堆栈上 而%i只会导致printf从该堆栈值中分割sizeof(int)

您可以通过简单地使用memcpy手动并以定义的方式完成所有操作:

#include <stdio.h>
#include <string.h>
typedef   struct 
 { 
    char duo_word[8]; 
 } duo_word;


int main()
{
    duo_word duo_word_inst = { .duo_word = { 'º', '\b', '\x1', '\0', 'À', '\xe', '2', 'a' } };
    int x;
    memcpy(&x, &duo_word_inst, sizeof(x));
    printf("          %i ", x); //prints 67770 too

#if UNDEFINED_BEHAVIOR
    printf("          %i ", duo_word_inst); // gives 67770 but how?
#endif
    return 0;
}

(更好的方法是在dbush的答案中使用bitops粘贴值,从而避免实现定义的行为。)

答案 2 :(得分:0)

对于与您认为正在解决的问题不同的问题,您的代码可能是错误的解决方案。

首先,数组char [8]不能用于可靠地存储整数值。这是因为char类型具有实现定义的签名。这意味着编译器可以随心所欲地将其实现为有符号或无符号。在这个内部,你将角色存储在基本角色之外,所以不知道你的代码会做什么。

如果您希望存储原始数据,则必须使用uint8_t中的stdint.h

然后正如其他人所指出的那样,你不能使用%i打印结构,也不能打印字符数组。如果你很幸运,你会得到某种看似确定的行为,但正式地说这是完全未定义的行为。在你的情况下,它可能将字节视为一个4字节的小端数,'º', '\b', '\x1', '\0'给出了十六进制00 01 08 BA,而这又是dec 67770.该程序可能会崩溃或打印垃圾,因为你依赖未定义的行为。它今天可以工作,明天也会崩溃。

为了确定性地,便携且可靠地获得值67770,您可以执行以下操作:

#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

typedef union
{
    uint8_t  bytes [8];
    uint32_t ints  [2];
} duo_word;

int main (void)
{
  duo_word dw = { .bytes = { 0xBA, 0x08, 0x01, 0x00 } };
  printf("%"PRIu32, dw.ints[0]);
}

这使用&#34;类型惩罚&#34;通过一个联合,这在C中是可以的(但不是在C ++中)。这仍然假设您正在使用一个小端CPU。对于真正的可移植代码,您必须改为使用位移。