从不兼容的指针类型警告中分配
问题描述:
我正在读一本名为“Advanced_C”的书,并尝试编译示例代码“POINTERS.C”。从不兼容的指针类型警告中分配
我已经构建并从代码块运行它,并尝试从Linux的cc,但我收到警告“从不兼容的指针类型赋值”。
#include <stdio.h>
#include<string.h>
int main(void);
int main()
{
int nCounter = 33;
int *pnCounter = (int *)NULL;
char szSaying[] =
{
"Firestone's Law of Forecasting: \n"
"Chicken Little only has to be right once.\n\n"
};
char *pszSaying = (char *)NULL;
printf(
"nCounter | pnCounter | *(pnCounter) | pszSaying | "
"szSaying[0] | szSaying[0-20]\n");
printf("%8d | %8p | %8d | %8p | %c | %20.20s\n",
nCounter,
pnCounter,
*(pnCounter),
pszSaying,
*(pszSaying),
szSaying);
printf("pnCounter = &nCounter; \n");
pnCounter = &nCounter;
printf("%8d | %8p | %8d | %8p | %c | %20.20s\n",
nCounter,
pnCounter,
*(pnCounter),
pszSaying,
*(pszSaying),
szSaying);
printf("pszSaying = szSaying; \n");
pszSaying = szSaying;
printf("%8d | %8p | %8d | %8p | %c | %20.20s\n",
nCounter,
pnCounter,
*(pnCounter),
pszSaying,
*(pszSaying),
szSaying);
printf("pszSaying = &szSaying; \n");
pszSaying = &szSaying;
printf("%8d | %8p | %8d | %8p | %c | %20.20s\n",
nCounter,
pnCounter,
*(pnCounter),
pszSaying,
*(pszSaying),
szSaying);
printf("pszSaying = &szSaying[0]; \n");
pszSaying = &szSaying[0];
printf("%8d | %8p | %8d | %8p | %c | %20.20s\n",
nCounter,
pnCounter,
*(pnCounter),
pszSaying,
*(pszSaying),
szSaying);
printf("*(pnCounter) = 1234; \n");
*(pnCounter) = 1234;
printf("%8d | %8p | %8d | %8p | %c | %20.20s\n",
nCounter,
pnCounter,
*(pnCounter),
pszSaying,
*(pszSaying),
szSaying);
return (0);
}
我是C编程新手。
谢谢!
答
szSaying
被声明为char
的数组,而pszSaying
被声明为指向char
的指针。在该表达式中:
pszSaying = szSaying,
szSaying
,这是一个数组,被转换为指针char
,并分配给pszSaying
是有效的。但是,在espression:
pszSaying = &szSaying
&szSaying
是指向的char
秒的阵列。这不同于指向char
的指针。这是关于不兼容的指针类型警告的原因。
这是我用gcc file.c -std=c99 -Wall -Wextra -pedantic
进行编译时得到的唯一警告。那么,在您拨打printf()
的电话中,还有大量关于%p
格式说明符的警告。在打印其值之前,您应该使用cast pointers to (void *)
。
通过铸造所有指针到(void *)
的打印之前,以及修改这些行:
char (*parrSaying)[] = NULL;
...
printf("parrSaying = &szSaying; \n");
parrSaying = &szSaying;
printf("%8d | %8p | %8d | %8p | %c | %20.20s\n",
nCounter,
(void *) pnCounter,
*(pnCounter),
(void *) parrSaying,
(*parrSaying)[0],
szSaying);
所有的警告的被除去。在这里,parrSaying
被声明为指向数组char
的指针,并初始化为NULL。但是,在处理了警告之后,还有另一个问题:您试图取消引用NULL指针!将指针初始化为NULL是很好的(虽然没有理由将NULL转换为(char *)
或其他),因为如果你没有这些引用将访问内存中的一些随机位置。但是解引用NULL指针是未定义的行为。你需要让他们发生之前首次尝试取消引用移动这两个指针赋值和打印他们的价值观:
pnCounter = &nCounter;
pszSaying = szSaying;
做了这些改变,你的代码在编译时没有警告和运行我的系统上,给以下输出:
nCounter | pnCounter | *(pnCounter) | pszSaying | szSaying[0] | szSaying[0-20]
33 | 0x7ffd3bd36bc4 | 33 | 0x7ffd3bd36be0 | F | Firestone's Law of F
pnCounter = &nCounter;
33 | 0x7ffd3bd36bc4 | 33 | 0x7ffd3bd36be0 | F | Firestone's Law of F
pszSaying = szSaying;
33 | 0x7ffd3bd36bc4 | 33 | 0x7ffd3bd36be0 | F | Firestone's Law of F
parrSaying = &szSaying;
33 | 0x7ffd3bd36bc4 | 33 | 0x7ffd3bd36be0 | F | Firestone's Law of F
pszSaying = &szSaying[0];
33 | 0x7ffd3bd36bc4 | 33 | 0x7ffd3bd36be0 | F | Firestone's Law of F
*(pnCounter) = 1234;
1234 | 0x7ffd3bd36bc4 | 1234 | 0x7ffd3bd36be0 | F | Firestone's Law of F
__哪里有这个警告? – tkausl
你的问题是什么? –
'pszSaying =&szSaying;':'pszSaying'是一个char *'szSaying'是一个char **' –