0

私はこの質問が以前に尋ねられたことを知っています。それはGoogleやこのサイトにもありますが、人々がそれを説明しても理解できません. 私は理解するのにあまりにも多くの時間を費やしてきましたが、まだ理解できていません。私が理解していない基本的なことがあるということを理解してください...さあ、始めましょう。

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は 2 番目のパラメーターのメモリ位置へのポインターを想定しています。これは、渡された整数から構築された結果の文字列を格納する場所です。しかし、あなたはそれをパスしsecsました - uint16_t. itoaコンパイラは、その整数に含まれる値が、結果の文字列を配置するアドレスとして使用されることを警告しています。

この種のことは、ほとんどのターゲットで segfault を引き起こしますが、私は Proteus に慣れていません。

とにかく、例として、itoa警告を修正するには、次のようなものを使用します。

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

それが役立つことを願っています。

于 2016-04-12T22:36:32.443 に答える
1

これは、コンパイラが暗黙的にキャストすることを意味しますが、警告を発行してキャストしたことを通知するため、それがわかります。

数字を使用した例を次に示します。

float f = 1.0;
int i = f;

プラットフォーム、言語、およびコンパイラの設定に応じて、いくつかのシナリオが考えられます。

  • コンパイラは警告なしで暗黙的にキャストfloatintます (悪い)
  • 同上だが警告を発する(より良い)
  • 警告をエラーとして扱うようにコンパイラ設定が変更されました (安全、セキュリティ クリティカルなど...)

警告は、バグやエラーの可能性についての良いヒントであり、一般的には、それらを抑制したり無視したりするのではなく、修正することが賢明です。

あなたの特定のケースでは、私は探していましたがUSART_pustring、最初に見つけたのはこれでした:

void USART_putstring(char* StringPtr)

intこれ以上調べる必要はありません。予期しない関数に を渡すとchar*(この場合)、予期しない結果が生じる可能性があります。

解決

のドキュメントを読み、USART_putstring入力データを受け入れる正しい型に「変換」していることを確認してください。警告は自然に消えます。

編集:

+1 for Aenimated1

「整数」と「整数へのポインター」の違いも理解していることを確認してください。彼はそれをかなりうまく説明しました:)

于 2016-04-12T22:42:11.727 に答える
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引数は、"hardwood"、"carpet"、"linoleum"、または "tile" などの文字列である必要があります。家の床を赤いタイルにすることにしたので、電話をかけます。

finish_the_floors("red", "tile");

でも、床を張った人が戻ってきて、「ねえバディ、『赤』は床材じゃないし、『タイル』は色じゃないから、もう一度やってみる?」と言いました。今回は、誰かがあなたの間違いを見つけました。

最後に、関数があるとします

furnish_the_bathroom(char *bath_or_shower, int number_of_sinks)

wherebath_or_showerは文字列 "bathtub" または "shower" である必要があり、2 番目の引数は必要なシンクの数である必要があります。シンクが 2 つとバスタブが 1 つ必要だと判断し、不注意な方法を続けて、次のように呼び出します。

furnish_the_bathroom(2, "bathtub");

今度は、あなたの偽の「関数呼び出し」は、浴槽を作ろうとしている人には届きません。建築家の薄暗い甥で、彼の兄弟が彼を夏の間雇うように仕向けたのですが、トースター オーブンと 2 x 4 の違いさえわからない彼は、あなたからの指示を会社に伝える責任を負っています。労働者であり、彼でさえ何かがおかしいことに気付くことができます。「うーん、ちょっと待って」彼は泣き言を言う。「最初のものは文字列で、2番目のものは数字だと思っていましたか?」

それでは、あなたの質問に戻りましょう。それが基本的にここで起こっていることです。関数を呼び出すときは、正しい引数を正しい順序で渡す必要があります (ビルダーへの指示と同じように)。コンパイラはすべての間違いをキャッチすることはできませんが、ポインタを渡すはずの場所に int を渡すなど、ありえないほど間違ったことをしていることに少なくとも気付くことができます。

于 2016-04-12T23:04:38.290 に答える
1

整数はカウント用です。ポインターは、変数が見つかる可能性のある場所を抽象的に示すものです。

頭の中で物事を明確にするために、ポインターの具体的な実装が整数の実装と同じであるシステムを使用している場合でも、2 つを混同しないことをお勧めします。

「私はここで何をしているのか知っている」というキャストを書かない限り、整数をポインターに、またはその逆に変換するのはエラーです。

残念ながら、一部のコンパイラは「警告」を吐き出し、偽のバイナリを生成します。可能であれば、この場合にコンパイラに「エラー」を通知させるコンパイラ スイッチを使用できるかどうかを確認してください。

このエラーが表示された場合は、通常、コンパイラがポインターを提供することを期待していた場所に整数を提供したことを意味します。


あなたのコードで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 に答える