从不兼容的指针类型警告分配

时间:2016-11-04 15:17:34

标签: c pointers

我正在阅读一本名为" 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编程的新手。

谢谢!

1 个答案:

答案 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