【问题标题】:How to assign string value in C from void *?如何从 void * 在 C 中分配字符串值?
【发布时间】:2011-12-15 08:22:13
【问题描述】:

我正在 C 中实现 CMap,其中一部分需要将信息存储在我手动管理其内存的链表类型的结构中。所以这个struct的前4个字节是指向下一个struct的指针,下一段是字符串(键),最后一段是值。

void *e = ptr 定义了一个这样的链表。 然后,ptr + 4 指的是字符串部分的开头。 我想将该字符串值分配给另一个字符串,到目前为止我所做的是:

char *string = (char *)ptr + 4;

但是,我认为这是不对的。

【问题讨论】:

  • 为什么不能强制转换为结构,然后使用-> 操作符访问字段?
  • 怎么知道字符串的长度?它以零字节终止?你到底想做什么?您是否要复制字符串?或者只是访问它?如果它是一个以零结尾的 C 风格字符串,而您只想访问它的值,char *string=(char *)ptr + 4; 就可以了。 (虽然sizeof(void *) 会比 4 好——代码最终可能需要在 LP64 平台上运行。)

标签: c string struct void-pointers


【解决方案1】:

@ralu 是正确的,您应该使用结构。但是在复制字符串时也应该非常小心。在 C 中,没有像 C++、Java、Python 以及其他所有东西中那样的一流字符串对象。 :)

在 C 中,字符指针 (char*) 通常用作字符串,但它们实际上只是指向内存中某处以空字符结尾的字节数组的指针。复制字符指针与复制底层字符数组不同。为此,您需要为副本的字符提供内存。该内存可以位于堆栈(本地数组)、堆(使用 malloc 创建)或其他缓冲区。

在执行任何操作以确保目标缓冲区可以容纳它之前,您需要测量字符串的长度。请务必在长度上加一,以便为终止的 null 留出空间。

另请注意,标准库函数(strlen、strcpy、strncpy、strcat、snprintf、strdup 等)在终止 null 方面彼此略有不兼容。例如,strlen 返回字符数,不包括终止的 null,因此缓冲区需要比它返回的内容大一个字节才能保存内容。此外, strncpy 不保证空终止,而 snprintf 保证。滥用这些函数和 C 字符串通常是当今计算机系统中大量安全漏洞(更不用说错误)的原因。

除非您构建或使用可靠的库,否则 C 中的字符串和列表操作是乏味且容易出错的。您可以了解为什么发明了 C++ 和所有其他语言。

【讨论】:

    【解决方案2】:

    只引用结构而不是计算偏移量。

    //if data is structured this way
    struct struct_list_el
    {
      struct list_el * next; 
      char* str;
      int value;
    };
    typedef struct struct_list_el list_el;
    
    // than from void_pointer
    list_el* el;
    el = (list_el*) void_pointer;
    
    char * string;
    string = el->str;
    

    【讨论】:

    • 如果您使用结构体,则应确保所有内容在内存中正确对齐,否则您会在某些架构(例如 m68k)上遇到总线错误。
    • @hochl 什么?与 m68k 的区别在于它们是大端,而 PC 是小端。这意味着从一台机器向另一台机器发送整数可能会导致问题。
    • 我记得在 m68000 上,在非偶数地址访问大于字节的任何内容都会产生总线错误,但那是在 80 年代,也许较新的型号在在这种情况下,内部将内存访问分为两个访问。无论如何,编译器通常会插入填充字节,以便所有结构成员都处于可访问的偏移量(通常甚至是除字节之外的任何内容)。
    • 您可以使用宏#pragma pack(1) 来打包结构。我在冷火上使用这种方法没有问题。
    【解决方案3】:

    如果你想指向同一个字符串,你的代码很好,假设指针总是 4 字节宽。

    如果要复制字符串的内容,请使用 malloc 和 strcpy 创建一个新字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-08
      • 2012-04-03
      • 2020-12-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-12
      • 2015-09-15
      相关资源
      最近更新 更多