C 结构体指针算术

标签 c string pointers struct

我目前正在用 C 编写一个新的 String 结构,如下所示,并练习指针算术。

struct String {
    uint32_t check;
    uint32_t capacity;
    uint32_t length;
    char data[1];

} String;

我对这部分代码有点困惑

define STRING(s) ((String*)(s - 3*sizeof(uint32_t)))

void utstrfree(char* self) {

//    if(*(self - sizeof(uint32_t) * 3) == SIGNATURE) WHY DOES THIS NOT >WORK?

    assert((STRING(self)->check) == SIGNATURE);     //check if it's a >utstring

    free(self-sizeof(uint32_t) * 3);    //properly free the malloc and alternative could have been free(STRING(self))

}

我了解我的 STRING 宏如何工作并且它工作正常,但我不太确定为什么我的 if 语句不起作用。谁能给我解释一下吗?

最佳答案

正如 @AslakBerby 已经观察到的,我假设您的断言中的表达式确实有效,但它并不等于注释掉的 if 语句中的条件表达式。特别是,由于 selfchar *,因此表达式 *(self - sizeof(uint32_t) * 3) 的类型为 char ,而表达式 STRING(self)->check 的类型为 uint32_t。假设评估后者已经定义了行为,则前者仅产生后者的第一个字节,按照系统特定的存储顺序。

但总的来说,就这个通用方案的工作而言,它是脆弱且不安全的:

  • 它对 struct String 类型的表示进行了假设,但实现不需要满足这些假设;
  • 它经常超出数组范围,从而调用未定义的行为;
  • 它没有提供表示就地子字符串的机制;
  • 它提供了与标准库的字符串函数的足够互操作性,让用户期望获得比实际提供的更高的互操作性。

建议:

  • 依靠 offsetof() 计算结构内的相对位置。它更安全、更清晰。
  • 甚至不要尝试与纯 char 数组字符串进行直接互操作 - 按实际情况处理这些对象。毕竟,此类练习的重点通常不在于数据结构本身,而在于随之而来的改进函数,例如 strlen() 的 O(1) 版本。无需费尽心力来适应这些对象与标准库函数的使用。
  • 考虑使用指向数据的指针,而不是将数据直接嵌入到对象中。这肯定会更好地适应调整大小,并且它也可以支持就地子字符串。
  • 如果您确实将数据直接嵌入到对象中,请使用灵活的数组成员来执行此操作。

关于C 结构体指针算术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42260674/

相关文章:

c++ - 如何在 C++/C 代码中执行多个 gnuplot 命令

java - 使用 StringBuilder 将包含多种编码的 byte[] 转换为 String

c++ - 有没有办法通过函数指针调用运算符函数?

swift - 在 Apples Swift 3 beta 6 中使用 withMemoryRebound

char 指针在两种不同情况下的行为不同

c - 定义指向内存地址的指针并打印内容 C++

Ruby 删除方法(字符串操作)

Python/plotly : How to extract 'm' and 'b' from OLS line?

c - 数组和指针的区别

c - 按位移位与十六进制值的 AND 运算之间的差异