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)