Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 棘手的指针别名问题_C_Gcc_Clang_Strict Aliasing - Fatal编程技术网

C 棘手的指针别名问题

C 棘手的指针别名问题,c,gcc,clang,strict-aliasing,C,Gcc,Clang,Strict Aliasing,以下代码无法编译,因为编译器在调用PrintStrings()时抱怨char**与const char*const*不兼容。如果我将strs变量声明为const char**,那么对PrintStrings()的调用会起作用,但是memcpy()和free()调用会抱怨它们得到了常量类型。这个问题有什么解决办法吗?请注意,我不想在调用PrintStrings()时将strs强制转换为uncomptbiele类型const char*const*,因为我使用的是非常激进的编译器优化,它依赖于永不破

以下代码无法编译,因为编译器在调用
PrintStrings()
时抱怨
char**
const char*const*
不兼容。如果我将
strs
变量声明为
const char**
,那么对
PrintStrings()
的调用会起作用,但是
memcpy()
free()
调用会抱怨它们得到了常量类型。这个问题有什么解决办法吗?请注意,我不想在调用
PrintStrings()
时将
strs
强制转换为uncomptbiele类型
const char*const*
,因为我使用的是非常激进的编译器优化,它依赖于永不破坏别名规则

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void
PrintStrings(const char* const* strs)
{
    int x = 0;
    while(strs[x])
        printf("%s", strs[x++]);
}

int
main(void)
{
    int x = 0;

    /* If I make this "const char**" then the memcpy's and free's will fail,
     * but if I leave the const off then the call to PrintString() fails */

    char** strs = malloc(5 * sizeof(char*));

    strs[0] = malloc(128);
    memcpy(strs[0], "Hello", 1 + strlen("Hello"));

    strs[1] = malloc(128);
    memcpy(strs[1], " ", 1 + strlen(" "));

    strs[2] = malloc(128);
    memcpy(strs[2], "World!", 1 + strlen("World!"));

    strs[3] = malloc(128);
    memcpy(strs[3], "\n", 1 + strlen("\n"));

    strs[4] = NULL;

    PrintStrings(strs);

    while(strs[x])
        free(strs[x++]);
    free(strs);

    return 0;
}
#包括
#包括
#包括
无效的
打印字符串(常量字符*常量*字符串)
{
int x=0;
while(strs[x])
printf(“%s”,strs[x++]);
}
int
主(空)
{
int x=0;
/*如果我做了这个“const char**”,那么memcpy和free将失败,
*但是如果我不使用const,那么对PrintString()的调用就会失败*/
char**strs=malloc(5*sizeof(char*));
strs[0]=malloc(128);
memcpy(strs[0],“你好”,1+strlen(“你好”);
strs[1]=malloc(128);
memcpy(strs[1],“”,1+strlen(“”);
strs[2]=malloc(128);
memcpy(strs[2],“World!”,1+strlen(“World!”);
strs[3]=malloc(128);
memcpy(strs[3],“\n”,1+strlen(“\n”);
strs[4]=NULL;
打印字符串(STR);
while(strs[x])
免费(strs[x++]);
免费(strs);
返回0;
}
[编辑]


请删除此问题中的重复标记。我完全理解演员阵容无效的原因,与其他海报不同,这不是我要问的。诚然,我的问题和另一个问题都围绕着同一个编译器问题,但另一个问题是问编译器为什么首先要这样做,而我要求的是在一个非常具体和棘手的情况下解决问题。

更改代码,如下所示:

char const **strs = malloc(sizeof(char*) * 5);
char *s;

strs[0] = s = malloc(128);
memcpy(s, "Hello", 1 + strlen("Hello"));

strs[1] = s = malloc(128);
memcpy(s, " ", 1 + strlen(" "));

...

while(strs[x])
    free((char *) strs[x++]);

您需要
常量
。我不知道你说的“破坏别名规则”是什么意思。当您将指针(
const
或其他)传递给函数时,优化器可以看到函数体并证明它没有做任何邪恶的事情,或者它必须假设函数隐藏了指针的副本,从而使别名成为可能
const_cast
不会改变任何情况。顺便说一句,请小心,您必须执行
malloc(5*sizeof(char*))
。感谢您的输入。我更新了MALOC来修复O型,并从帖子的标签中删除C++标签,因为我在C中工作得很严格,没有“代码> const char *const */CODE >,对吧?应该是
const char**const
?我不认为这是重复的,因为他没有问为什么,而是问如何解决这个问题。那么我将如何处理free()调用?我想我必须在运行时缓存每个“s”值?这确实有效,很酷。你可以,但我只是将它们转换为
char*
void*
free
没有任何别名问题需要担心。在上下文之外扩展我的最后一条注释,比如
PrintStrings((char const*const*)strs)
看起来可疑,因为它的正确性取决于strs的类型。所以我不希望代码使用这样的强制转换。另一方面,像
free((char*)strs[0])
这样的语句就不那么令人担忧了,因为重要的是
strs[0]
被分配了
malloc
。这是一个非常好的观点。我认为这是最好的解决办法。将问题标记为答案如果你要求编译器“挑剔”(例如,gcc的Wcast qual),那么当你释放这个东西时,它会抱怨扔掉
常量,从它的角度来看,这是完全正确的。当然,编译器只能做这么多。。。一个双重演员可以做到这一点:
(void*)(uintpttr_t)strs[x++]
(ho-ho)