0

我知道以前有人问过这个问题。它遍布谷歌和这个网站,但当他们解释时我无法理解。我已经花了太多时间试图理解,但我仍然不明白,所以请尝试理解有一些基本的东西我不理解......我们开始吧。

在 Proteus 上用 C 语言编程时,我经常收到警告和/或错误(在这种情况下为警告):

makes pointer from integer without a cast

我不明白。就像我说的,我已经花了几个小时研究它,我知道它与类型和/或指针有关,等等。请有人像正常人一样向我解释。

另外,我得到了很多。是否有可能在没有强制转换的情况下从其他类型的变量中获得此警告?一个人物?我现在将如何解决这个问题,并在将来避免它?

这是上下文...

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "stdlib.h"
#include "USART.h"
#include "I2C.h"
#include "ds1307.h"

void Wait()
{
   uint8_t i;
   for(i=0;i<20;i++)
      _delay_loop_2(0);
}

uint8_t ss,mm,hh,dd,nn,yy,x;    // Appropriately labeled variables
uint16_t sec[3],min[3],hr[3],day[3],month[3],year[3],mode[2];
uint16_t secs,mins,hrs,days,months,years,modes;

int main(void)
{
   _delay_ms(50);
   USART_interrupt_init();          // 
   USART_send('\r');                // Send carriage return
   _delay_ms(100);              // Allows for the LCD module to initialize

   I2CInit();                   // Initialize i2c Bus
   DS1307Write(0x07,0x10);          // Blink output at 1Hz
   while(1)
      {
     int i=0;
     /* SECONDS */
     DS1307Read(0x00,&ss);      // Read seconds address
     /* MINUTES */
     DS1307Read(0x01,&mm);      // Read minutes address
     /* HOURS */
     DS1307Read(0x02,&hh);      // Read hours address
     /* DAY */
     DS1307Read(0x04,&dd);      // Read hours address
     /* MONTH */
     DS1307Read(0x05,&nn);      // Read hours address
     /* YEAR */
     DS1307Read(0x06,&yy);      // Read hours address
     for(i=0;i<5;i++)
     {Wait();i++;}

     sec[0]=(0b00001111 & ss);
     sec[1]=((0b01110000 & ss)>>4);
     sec[2]='\0';
     itoa(sec[0],secs,10);

     USART_putstring(secs); // place string in buffer

和2个错误:

../main.c:59: warning: passing argument 2 of 'itoa' makes pointer from integer without a cast

../main.c:62: warning: passing argument 1 of 'USART_putstring' makes pointer from integer without a cast
4

4 回答 4

2

您的编译器告诉您该函数需要一个指针,但您传递了一个整数。因此,它将自动将您的整数值视为地址并将其用作指针。

例如,itoa它的第二个参数需要一个指向内存位置的指针——它存储从传递给它的整数构建的结果字符串。但是你已经通过secs了 - 一个 uint16_t。编译器警告您,该整数中的任何值都将用作itoa放置其结果字符串的地址。

这种事情会导致大多数目标出现段错误,但我对 Proteus 不熟悉。

无论如何,例如,要修复itoa警告,请使用以下内容:

char secs[3];
...
itoa(sec[0], secs, 10);

希望有帮助。

于 2016-04-12T22:36:32.443 回答
1

所以这里有一个完全不同的答案,在一个更高的层次上,为了清楚地说明这一点,我们将从 C 编程退后一步,讨论建造房屋。我们将向建造房屋的人发出指示,但我们会想象我们有一些严格的、规范的方式来做这件事,有点像函数调用。

假设是时候粉刷房子的外面了。paint_the_house()假设有一个看起来像这样的“函数” :

paint_the_house(char *main_color, char *trim_color);

你决定要在黄色房子上装饰白色,所以你“打电话”

paint_the_house("white", "yellow");

画家们尽职尽责地将房子漆成白色,并带有黄色的饰边。哎呀!你犯了一个错误,没有人发现它,现在房子颜色不对。

假设有另一个函数,finish_the_floors()看起来像这样:

finish_the_floors(char *floor_material, char *color)

floor_material参数应该是一个字符串,如“硬木”、“地毯”、“油毡”或“瓷砖” 。你决定要在你的房子里铺红砖,所以你打电话

finish_the_floors("red", "tile");

但是安装地板的人回来说:“听着,哥们,‘红色’不是地板材料,‘瓷砖’不是颜色,你要不要再试一次?” 这一次,有人发现了你的错误。

最后,假设有一个函数

furnish_the_bathroom(char *bath_or_shower, int number_of_sinks)

wherebath_or_shower应该是字符串“bathtub”或“shower”,第二个参数应该是你想要的水槽数量。你决定要两个水槽和一个浴缸,然后继续你粗心的方式,你打电话给:

furnish_the_bathroom(2, "bathtub");

这一次,你的虚假“函数调用”甚至没有传给要建造浴缸的人。建筑师的昏暗的侄子,他的兄弟诱使他在夏天雇用他,他甚至无法区分烤箱和 2×4 之间的区别,他负责将您的指示转达给劳动者,就连他也能看出哪里不对劲。“嗯,等一下,”他抱怨道。“我以为第一件事应该是一个字符串,第二件事应该是一个数字?”

现在我们可以回到你的问题,因为这基本上就是这里发生的事情。当你调用一个函数时,你必须以正确的顺序传递正确的参数(就像你给建造者的指令一样)。编译器无法捕捉到你所有的错误,但它至少可以注意到你正在做一些不可能的错误,比如在你应该传递一个指针的地方传递一个 int。

于 2016-04-12T23:04:38.290 回答
1

这意味着编译器会为您隐式转换它,但是,它会通过发出警告来通知您它所做的事情,以便您知道这一点。

这是一个使用数字的示例:

float f = 1.0;
int i = f;

根据平台、语言和编译器设置,可能会出现以下几种情况:

  • 编译器隐式转换floatint没有警告(坏)
  • 同上但发出警告(更好)
  • 编译器设置更改为将警告视为错误(安全、安全关键等...)

警告是对可能的错误或错误的一个很好的提示,通常明智的做法是修复它们而不是抑制或忽略它们。

在你的具体情况下,我一直在寻找一个USART_pustring,我发现的第一个是这个:

无效 USART_putstring(char* StringPtr)

无需进一步研究,将 an 传递int给期望的函数char*(如果是这种情况),“可能”会产生意想不到的结果。

解决方案

阅读文档USART_putstring并确保您将输入数据“转换”为它接受的正确类型,警告将自行消失。

编辑:

+1动画1

确保您也了解“整数”和“整数指针”之间的区别,他解释得很好:)

于 2016-04-12T22:42:11.727 回答
1

整数用于计数。指针是可以找到变量的抽象指示。

为了让您头脑清晰,最好不要将两者混为一谈,即使您在一个指针的具体实现与整数的实现相同的系统上也是如此。

将整数转换为指针是错误的,反之亦然,除非你写一个演员表说“我知道我在这里做什么”。

不幸的是,一些编译器会吐出“警告”,然后生成一个伪造的二进制文件。如果可能的话,看看你是否可以使用编译器开关来让编译器在这种情况下说“错误”。

如果你看到这个错误,这通常意味着你提供了一个整数,编译器希望你提供一个指针。


在您的代码中,您这样做itoa(sec[0],secs,10);是一个问题。itoa函数签名是:

char * itoa ( int value, char * str, int base );

您为参数 提供secs了一个uint16_t(16 位整数)char * str。这是一个错误,因为它需要一个对象的地址,但您提供了一个数字。


要解决此问题,您需要停止为指针参数提供整数。

有关如何将输出转换为DS1307Read显示字符串的帮助,请发布一个专门询问该问题的问题。

于 2016-04-12T22:48:59.280 回答