LINUX.ORG.RU

История изменений

Исправление gentoo_root, (текущая версия) :

Значит, если функция принимает char*, то за этим чаром может быть любой объект, т. к. к любому объекту можно обращаться как к char

Да.

Character pointer types are often used in the bytewise manipulation of objects; a byte stored through such a character pointer may well end up in an object of any type.

Через char * можно рулить байтиками объектов, байтики по этому указателю могут принадлежать любому объекту. Это означает всего лишь, что char * может оказаться указывающим на любой объект, это не значит, что если на что-то указывает char *, мы можем это переинтерпретировать как другой тип. Если бы было так, можно было бы объявить int a, привести (short *)(char *)&a и получить указатель уже на short. У меня есть такой пример, в нём ломается strict aliasing на gcc 4.9.2, x86_64:

#include <stdio.h>

// gcc 5.c -o 5 -O3 -Wall -Wextra -Wstrict-aliasing=3
// no warning

// gcc 5.c -o 5 -O3 -Wall -Wextra -Wstrict-aliasing=2
// no warning

// gcc 5.c -o 5 -O3 -Wall -Wextra -Wstrict-aliasing=1
// no warning

// strict aliasing is broken

int global;

int modify(char *test)
{
        global = 'a';
        *(short *)test = 'b';
        return global;
}

int main()
{
        printf("%c\n", modify((char *)&global));
        return 0;
}

Программа выводит a, а с -fno-strict-aliasing выводит b.

Вот так вот. А объяснение простое — мы обращаемся к объекту эффективного типа int по lvalue типа short, а short не является совместимым типом с int и не подходит под остальные пункты.

Исходная версия gentoo_root, :

Значит, если функция принимает char*, то за этим чаром может быть любой объект, т. к. к любому объекту можно обращаться как к char

Да.

Character pointer types are often used in the bytewise manipulation of objects; a byte stored through such a character pointer may well end up in an object of any type.

Через char * можно рулить байтиками объектов, байтики по этому указателю могут принадлежать любому объекту. Это означает всего лишь, что char * может оказаться указывающим на любой объект, это не значит, что если на что-то указывает char *, мы можем это переинтерпретировать как другой тип. Если бы было так, можно было бы объявить int a, привести (short *)(char *)&a и получить указатель уже на short. У меня есть такой пример, в нём ломается strict aliasing на gcc 4.9.2, x86_64:

#include <stdio.h>

// gcc 5.c -o 5 -O3 -Wall -Wextra -Wstrict-aliasing=3
// no warning

// gcc 5.c -o 5 -O3 -Wall -Wextra -Wstrict-aliasing=2
// no warning

// gcc 5.c -o 5 -O3 -Wall -Wextra -Wstrict-aliasing=1
// no warning

// strict aliasing is broken

int global;

int modify(char *test)
{
        global = 'a';
        *(short *)test = 'b';
        return global;
}

int main()
{
        printf("%c\n", modify((char *)&global));
        return 0;
}

Вот так вот. А объяснение простое — мы обращаемся к объекту эффективного типа int по lvalue типа short, а short не является совместимым типом с int и не подходит под остальные пункты.