【问题标题】:Write and read an integer in a char *在 char * 中写入和读取整数
【发布时间】:2015-03-23 20:51:03
【问题描述】:

我正在用 c 编写一个小服务器(一个聊天服务器),我想在我的 char *data 中写入和读取一个整数(以及其他类型的变量,如 short int、unsigned int blablabla)。

我有一个结构 DataOutput :

typedef struct t_dataoutput
{
  char *data;
  unsigned int pos;
} DataOutput;

我有一个函数可以写一个 int :

int writeInt(DataOutput *out, int i)
{
  // here i resize my char *data
  out->data[out->pos] = (i >> 24);
  out->data[out->pos + 1] = (i >> 16) & 0xff;
  out->data[out->pos + 2] = (i >> 8) & 0xff;
  out->data[out->pos + 3] = i & 0xff;
  out->pos += 4;
}

在我的主要功能中,我想尝试我的代码:

int main()
{
  DataOutput out;

  out.writeInt(&out, 9000);
  printf("%d\n", (out.data[0] << 24) | (out.data[1] << 16) | (out.data[2] << 8) | (out.data[3]));
}

但结果并不好......为什么?我不明白:(

对不起我的英语我是法国人^^!

感谢您的帮助!

【问题讨论】:

    标签: c


    【解决方案1】:

    应将 DataOutput.data 强制为 unsigned char,因为 char 有时是有符号的,具体取决于编译器,并且将带符号的 char 转换或将它们强制转换为 int(甚至隐式)将传播符号位:

    typedef struct t_dataoutput
    {
      unsigned char *data;
      unsigned int pos;
    } DataOutput;
    

    out->data 的内存必须在填充之前分配。 您可以像这样在 writeInt 函数中使用 realloc:

    int writeInt(DataOutput *out, int i)
    {
      // here i resize my char *data
      out->data = realloc(out->data, out->pos + 4);
      // TODO: test if out->data == NULL --> not enough memory!
      out->data[out->pos] = (i >> 24) & 0xff;
      out->data[out->pos + 1] = (i >> 16) & 0xff;
      out->data[out->pos + 2] = (i >> 8) & 0xff;
      out->data[out->pos + 3] = i & 0xff;
      out->pos += 4;
    }
    

    【讨论】:

    • 好的,我明白了,但是用这个解决方案我不能写一个负整数?我认为我将毫无用处,但这只是一个问题。还有一个问题,使用 realloc 您必须使用 out->pos 添加当前缓冲区大小?还是 juste realloc(out->data, sizeof(int)) 好?如果我必须在 realloc 中添加当前大小,我认为我必须添加 1byte 才能获得正确的大小
    • 会传播符号位 甚至更复杂。根据标准,负整数右移是实现定义的行为,负整数左移是未定义的行为。
    • 你可以毫无问题地写负整数;在任何情况下,在解码时,您都必须知道数据代表什么,以便正确转换。 realloc(out-&gt;data, sizeof(int)) 会将您的数据减少到 4 个字节,删除其余的,所以在我看来这不好,尤其是当 pos != 0 时。您不必再添加一个字节:您正在写入 4 个字节,所以您只需还需要四个字节的内存。
    【解决方案2】:

    当然我用这个函数初始化我的结构:

    void initDataOutput(DataOutput *out)
    {
      out->data = NULL;
      out->pos = 0;
    }
    

    但我做不到:

    DataOutput out;
    char tmp[4];
    out.data = tmp;
    out.pos = 0;
    

    因为在我的代码中我可以写这样的东西,例如:

    DataOutput out;
    writeInt(&out, 1);
    writeString(&out, "Hello");
    sendData(&out);
    

    int 是一种数据包 id,“Hello”是连接消息,但如果是其他 id,则与 out->data 中的信息不同

    抱歉,我不明白你说的是什么意思:避免移动有符号整数和字符

    我必须在我的 DataOutput 结构中使用 unsigned char *data 吗?

    【讨论】:

    • 如果您对某个答案发表评论,请使用“添加评论”而不是其他答案。 (是的,如果您要添加一些代码,这有点困难。在这种情况下,请考虑编辑原始问题)。二、为什么将data设置为NULL?你在某处分配缓冲区吗?关于班次:严格来说,如果您进行班次,您应该使用unsigned intunsigned char。在实践中,使用int/char 存储数据,并在转移之前将它们转换为unsigned,可能会起作用。
    • 我将数据初始化为 NULL,因为它是一个指针 :) 我在写入数据后分配缓冲区
    • 是的,我的意思是你为什么不为data分配内存?还是在其他地方完成?
    • 这是在写我的数据之前完成的 :) 但我没有在帖子中写它,因为我觉得它没用理解。这只是对 realloc 的调用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 2023-03-04
    相关资源
    最近更新 更多