需要帮助解决警告:取消引用类型双关指针将破坏严格别名规则

工作区域

我正在研究一组 C 代码来优化它。我在修复损坏的代码时遇到了警告。

环境是Linux,C99,用-Wall -O2flags编译

最初的结构文本定义如下:

    struct text {
        char count[2];
        char head[5];
        char textdata[5];
    }

代码是返回指针T1T2预期headtextdata字符串:

int main(void) {
    struct text *T1;
    char *T2;
    char data[] = "02abcdeabcde";

    T1 = (struct text *)data;
    T2 = T1->textdata;
    gettextptr((char *)T1, T2);
    printf("\nT1 = %s\nT2 = %s\n", (char *)T1, T2);
    return (0);
}

void gettextptr(char *T1, char *T2) {
    struct text *p;
    int count;

    p = (struct text *)T1;
    count = (p->count[0] - '0') * 10 + (p->count[1] - '0');

    while (count--) {
        if (memcmp(T2, T1, 2) == 0) {
            T1 += 2;
            T2 += 2;
        }
    }
}

这没有按预期工作。预计会返回第一个“c”和最后一个“e”的地址。通过GDB,我发现,一旦从执行指针返回gettextptr()到父函数,它不保留的地址T1T2然后我尝试了另一种使用双指针“按引用调用”的方法:

int main(void) {
    struct text *T1;
    char *T2;
    char data[] = "02abcdeabcde";

    T1 = (struct text *)data;
    T2 = T1->textdata;
    gettextptr((char **)&T1, &T2);
    printf("\nT1 = %s\nT2 = %s\n", (char *)T1, T2);
    return (0);
}

void gettextptr(char **T1, char **T2) {
    struct text *p;
    int count;

    p = (struct text *)(*T1);
    count = (p->count[0] - '0') * 10 + (p->count[1] - '0');

    while (count--) {
        if (memcmp(*T2, *T1, 2) == 0) {
            *T1 += 2;
            *T2 += 2;
        }
    }
}

当我使用 编译此代码时-Wall -O2,我收到以下 GCC 警告:

 pointer.c: In function ‘main’:
 pointer.c:23: warning: dereferencing type-punned pointer will break strict-aliasing rules

所以:

  1. 在第一种情况下,代码是按值调用的吗?

  2. 是不是(char **)允许,同时保持严格别名规则铸造?

  3. 我缺少什么来解决此警告?

约翰·博林格

严格的别名规则是标准的第 6.5/7 段它基本上说你只能通过兼容类型的左值访问一个对象,可能还有额外的限定符;相应的有符号/无符号类型;数组、结构或联合类型及其成员之一,或字符类型。您收到的诊断报告说您的代码违反了该规则,并且多次违反了该规则。

你很早就陷入困境:

    T1 = (struct text *)data;

这种转换是允许的,虽然不能保证得到的指针正确对齐,但在T1不违反严格的别名规则的情况下,你无能为力特别是,如果你用*or取消引用它->——这实际上是你接下来要做的事情——那么你访问一个char数组就好像它是一个struct text. 这是不允许的,尽管反过来会是另一回事。

转换T1为 achar *并通过该指针访问指向的数组,正如您稍后所做的那样,是您可以用它做的一些事情

gettextexpr()是相同的(两个版本)。它执行与上述相同类型的转换,并在访问 时取消引用转换后的指针p->count由此产生的行为违反了严格的别名规则,因此是未定义的。然而,GCC 在第二种情况下实际上抱怨的可能是访问*T1好像它是一个char *,而实际上它是struct text *另一个,单独的,严格的别名违规。

因此,针对您的具体问题:

  1. 在第一种情况下,代码是按值调用的吗?

C只有按值传递,所以是的。在第一种情况下,您char按值传递两个指针,然后您可以使用它们来修改调用者的char数据。在第二种情况下,您char *按值传递两个指针,您可以并且确实使用它们来修改调用者的char *变量。

  1. 在保持严格的别名规则的同时,是否允许 (char **) 进行转换?

不,绝对不是。强制转换 char *(not char **) 可以允许您通过结果指针访问对象的表示,因为取消引用 achar *会产生字符类型的左值,但没有任何类型可以没有严格别名含义的情况下进行一般转换

  1. 我缺少什么来解决此警告?

你错过了你试图做的事情从根本上不允许的。C 不允许像访问, 句点char一样访问数组struct text尽管如此,编译器可能会接受这样做的代码,但其行为是未定义的。

通过放弃强制转换结构方法来解决警告,无论如何,这种方法只提供语法糖粉。摆脱所有的铸造并编写实际上更简单和更清晰:

    count = ((*T1)[0] - '0') * 10 + ((*T1)[1] - '0');

摆脱所有的铸造用途也许更清楚sscanf

    sscanf(*T1, "%2d", &count);

另请注意,即使允许,您的特定访问模式似乎对结构成员的布局做出了不由语言证明的假设。实现可能会在成员之间和最后一个成员之后使用任意填充,而您的代码无法适应这种情况。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

警告的后果“取消引用类型化的指针将破坏严格的别名规则”

来自分类Dev

调用free()包装器:取消引用类型标记的指针将破坏严格的别名规则

来自分类Dev

取消引用类型标记的指针将破坏严格的别名规则:将字节数组转换为数字

来自分类Dev

取消引用类型标记的指针将破坏严格的混叠规则:将字节数组转换为数字

来自分类Dev

取消引用类型化指针会破坏严格混叠规则[-Wstrict-aliasing]

来自分类Dev

取消引用类型化指针会破坏严格混叠规则[-Wstrict-aliasing]

来自分类Dev

带解引用类型指针的stof()/ stoi()将破坏严格的混叠规则

来自分类Dev

具有解引用类型指针的stof()/ stoi()会破坏严格混叠规则

来自分类Dev

兼容类型与严格的别名规则

来自分类Dev

强制转换为不相关的引用类型是否违反严格的别名规则?

来自分类Dev

定位指针,引用,取消引用规则:

来自分类Dev

通过引用访问是否违反严格的别名规则?

来自分类Dev

与严格别名相关的有效类型规则

来自分类Dev

将取消引用的智能指针的地址传递给需要原始指针的函数

来自分类Dev

将取消引用的指针(即按值)传递给需要指针的函数

来自分类Dev

即使在类型转换之后,每次都需要取消引用 void 指针吗?

来自分类Dev

数组中严格的别名规则

来自分类Dev

使用指针转换来存储/广播值:我是否违反了严格的别名规则?

来自分类Dev

将指针取消引用为for循环条件?

来自分类Dev

转换为char *然后转换回原始类型是否会破坏严格的别名?

来自分类Dev

在C中使用typedef结构时,将指向不完整类型错误的指针取消引用

来自分类Dev

将指针取消引用到不完整类型的链表-C

来自分类Dev

标准定义了哪种类型的双关/指针魔术?

来自分类Dev

如何在不始终取消引用指针的情况下解决“无法移出取消引用”错误?

来自分类Dev

C ++ 11中严格的别名规则

来自分类Dev

此代码是否违反严格的别名规则?

来自分类Dev

再次:严格的别名规则和char *

来自分类Dev

严格的别名规则可以吗?

来自分类Dev

这是否违反严格的别名规则?

Related 相关文章

  1. 1

    警告的后果“取消引用类型化的指针将破坏严格的别名规则”

  2. 2

    调用free()包装器:取消引用类型标记的指针将破坏严格的别名规则

  3. 3

    取消引用类型标记的指针将破坏严格的别名规则:将字节数组转换为数字

  4. 4

    取消引用类型标记的指针将破坏严格的混叠规则:将字节数组转换为数字

  5. 5

    取消引用类型化指针会破坏严格混叠规则[-Wstrict-aliasing]

  6. 6

    取消引用类型化指针会破坏严格混叠规则[-Wstrict-aliasing]

  7. 7

    带解引用类型指针的stof()/ stoi()将破坏严格的混叠规则

  8. 8

    具有解引用类型指针的stof()/ stoi()会破坏严格混叠规则

  9. 9

    兼容类型与严格的别名规则

  10. 10

    强制转换为不相关的引用类型是否违反严格的别名规则?

  11. 11

    定位指针,引用,取消引用规则:

  12. 12

    通过引用访问是否违反严格的别名规则?

  13. 13

    与严格别名相关的有效类型规则

  14. 14

    将取消引用的智能指针的地址传递给需要原始指针的函数

  15. 15

    将取消引用的指针(即按值)传递给需要指针的函数

  16. 16

    即使在类型转换之后,每次都需要取消引用 void 指针吗?

  17. 17

    数组中严格的别名规则

  18. 18

    使用指针转换来存储/广播值:我是否违反了严格的别名规则?

  19. 19

    将指针取消引用为for循环条件?

  20. 20

    转换为char *然后转换回原始类型是否会破坏严格的别名?

  21. 21

    在C中使用typedef结构时,将指向不完整类型错误的指针取消引用

  22. 22

    将指针取消引用到不完整类型的链表-C

  23. 23

    标准定义了哪种类型的双关/指针魔术?

  24. 24

    如何在不始终取消引用指针的情况下解决“无法移出取消引用”错误?

  25. 25

    C ++ 11中严格的别名规则

  26. 26

    此代码是否违反严格的别名规则?

  27. 27

    再次:严格的别名规则和char *

  28. 28

    严格的别名规则可以吗?

  29. 29

    这是否违反严格的别名规则?

热门标签

归档