我正在阅读一本名为" Advanced_C"的书,并尝试编写示例代码" POINTERS.C"。
我已经从codeblocks构建并运行它,并且还尝试了来自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编程的新手。
谢谢!
答案 0 :(得分:0)
szSaying
被声明为char
的数组,pszSaying
被声明为char
的指针。在表达式中:
pszSaying = szSaying,
szSaying
是一个数组,转换为指向char
的指针,对pszSaying
的赋值有效。但是,在表达中:
pszSaying = &szSaying
&szSaying
是指向char
数组的指针。这与指向char
的指针不同。这是警告不兼容指针类型的原因。
这是我用gcc file.c -std=c99 -Wall -Wextra -pedantic
编译时得到的唯一警告。好吧,您对%p
的调用中还有大量有关printf()
格式说明符的警告。在打印其值之前,您应该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
s数组的指针,并初始化为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