【问题标题】:How to copy a char[] in c into my struct如何将 c 中的 char[] 复制到我的结构中
【发布时间】:2009-12-07 04:23:15
【问题描述】:

我正在尝试通过 UDP 套接字发送我的结构。

结构包{ 整数序列号; 字符数据[缓冲区大小]; };

所以我的发件人

bytes = sizeof(packet);
char sending[bytes];
bzero(sending, bytes);
memcpy((void *) sending, (void *) &packet, sizeof(bytes));
bytes = sendto(sockfd, sending, sizeof(sending), 0,
    (struct sockaddr *) &client, clientSize);

所以我希望将我的结构复制到 Char[] 中。

在我的接收器上

int bytes;
bytes = sizeof(struct Packet);
char recv[bytes];
bytes = recvfrom(sockfd, recv, bytes, 0,
    (struct sockaddr *) &client, &clientSize);
memcpy((void *) currentpkt, (void *) recv, bytes);

但是在接收器上 memcpy((void *) currentpkt, (void *) recv, bytes); 我得到一个错误:

错误:无法转换为指针类型

我做错了什么?有没有更好的方法通过 UDP 套接字发送我的结构?

***** 更新 *****

感谢大家的回答。最后我错过了“&”,但我的代码现在看起来像这样。

发件人:

void udt_send(struct Packet packet) {
    int bytes;
    bytes = sendto(sockfd, (char *) &packet, sizeof(packet), 0,
            (struct sockaddr *) &client, clientSize);
}

接收者:

bytes = recvfrom(sockfd, (char *) &currentpkt, bytes, 0,
        (struct sockaddr *) &client, &clientSize);

在 C 语言中,我们可以将其转换为 char 并发送字节,这很好。

【问题讨论】:

  • 结构数据包 currentpkt; // 全局变量
  • 问题一:当你不需要使用全局变量时,不要使用全局变量。

标签: c sockets struct udp memcpy


【解决方案1】:

currentpkt 是结构体类型;你需要得到一个指向结构的指针才能让它工作:

memcpy(&currentpkt, recv, bytes);

对于您的第二个问题,您还有其他一些问题。如果您在一个数据包中收到比sizeof(struct Packet) 更多的字节怎么办?正如现在所写的那样,您将超出您的结构。

如果客户端和服务器应用程序使用不同的编译器或设置进行编译,或者在具有不同字节顺序的平台上编译会怎样?在这种情况下,结构在两个平台上的大小可能不同,并且在内存中的布局也可能不同。

【讨论】:

  • @Bernie:确保你解决了詹姆斯的其他观点。对于超限,更好地利用memcpy的第三个参数;只要确保您处理的数据过多和过少即可。对于字节顺序,请查看 ntoh*hton* 函数(例如 ntohl)。全局变量可以转换为函数参数,或者(有时)添加为适当结构的字段。
【解决方案2】:

所以我认为currentpktstruct Packet,而您的真正意思是说&currentpkt

我可能还注意到memcpy() 已经有void * 参数,因此不需要(void *) 强制转换。

【讨论】:

  • 感谢您的提示。我将删除那些无效的 *。
【解决方案3】:

memcpy((void *) currentpkt, (void *) recv, bytes);

您的错误消息表明存在转换问题。 recv 可以,因为它是 char[](转换为 (void*) 没有问题)。问题一定是currentpkt不能是指针类型。

它没有在你的 sn-p 中声明,所以我不知道它是什么,但我会从那里开始。

【讨论】:

    【解决方案4】:

    从整个结构中执行 memcpy 确实是邪恶的 :-)。首先,数据可能会因架构而异。如果另一边的架构不同怎么办?使用 __packed 等关键字也不能在不同的编译器之间移植。

    据我所知,最好的方法是使用像 PHP 打包/解包这样的 API。这使得代码真正可移植,而无需使用编译器特定的丑陋关键字,例如 __packed。

    我没有在网上找到任何 C 的打包/解包,所以我自己写了。

    例如从二进制数据中解包两个单词:

       pbuf_unpack(p_bts, "ww", &hdr, &ver); 
    

    在哪里

       p_bts is binary data
       "ww" describes the data structure
       hdr and ver is where to put the datause an API like the PHP pack/unpack. 
    

    另一个更广泛的例子:

       pbuf_unpack(p_entry, "bbbbbbbbww",
          &atrb_mbr.def_boot_par, &atrb_mbr.head_start, &atrb_mbr.sec_start,
          &atrb_mbr.cyl_start, &atrb_mbr.type, &atrb_mbr.head_end, 
          &atrb_mbr.sec_end, &atrb_mbr.cyl_end, &atrb_mbr.start_sec_pbr,
          &atrb_mbr.sec_per_par);
    

    包装很简单:

       pbuf_pack(boot_buf, "sdsdhbhbhhbhhhwwbbbwsdsd", sizeof(fat_jmp_boot_t), 
          boot.jmp, sizeof(fat_oem_nm_t), boot.oem_nm, boot.n_bps, boot.n_spc, 
          boot.n_rs, boot.n_fs, boot.n_rde, boot.n_ts16, boot.media_des, 
          boot.n_fatsz16, boot.n_spt, boot.n_hds, boot.n_hs, boot.n_ts32, 
          boot.drv_no, boot.rsrvd1, boot.boot_sig, boot.vol_id, 
          sizeof(fat_vol_lbl_t), boot.lbl, sizeof(fat_vol_type_t), boot.type);
    

    它不仅可以创建可移植的代码,而且还很漂亮;)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-19
      • 2014-12-13
      • 2012-02-25
      • 1970-01-01
      • 2013-05-15
      • 1970-01-01
      • 2010-12-03
      • 1970-01-01
      相关资源
      最近更新 更多