14
volatile char* sevensegment_char_value;

void ss_load_char(volatile char *digits) {
    ...
    int l=strlen(digits);
    ...
 }

 ss_load_char(sevensegment_char_value);

上記の例では、avr-gcc コンパイラから警告が表示されました

Warning 6   passing argument 1 of 'strlen' discards 'volatile' qualifier from pointer target type [enabled by default]

だから私はどうにかして揮発性変数から非揮発性変数に値をコピーする必要がありますか? 安全な回避策は何ですか?

4

3 に答える 3

11

Cの「組み込み」回避策のようなものはありません。揮発性は、変数の内容(またはあなたの場合は変数が指しているメモリ)がコンパイラーに気付かれずに変更される可能性があることをコンパイラーに伝え、コンパイラーに強制しますレジスタに存在する可能性のあるコピーを使用するのではなく、データバスから直接データを読み取る。したがって、volatile キーワードは、コンパイラの最適化によって引き起こされる奇妙な動作を避けるために使用されます。(よろしければ、これについて詳しく説明できます)

あなたの場合、揮発性として宣言された文字バッファーがあります。たとえば、プログラムが ISR などの別のコンテキストでこのバッファーの内容を変更する場合、データの不整合を回避するために、ある種の同期メカニズム (特定の割り込みを無効にするなど) を実装する必要があります。「ロック」を取得した後 (割り込みを無効にする)、データをバイトごとにローカル (不揮発性) バッファーにコピーし、ルーチンの残りの部分でこのバッファーで作業することができます。

バッファーが読み取りアクセスのコンテキストの「外側」で変更されない場合は、使用しないため、volatile キーワードを省略することをお勧めします。

正しい解決策を判断するには、正確なユースケースについてもう少し情報が必要です。

于 2012-11-29T12:57:19.187 に答える
7

標準ライブラリ ルーチンは、volatileオブジェクトに対して機能するようには設計されていません。最も簡単な解決策は、揮発性メモリを操作する前に通常のメモリに読み込むことです。

void ss_load_char(volatile char *digits) {
  char buf[BUFSIZE];
  int i = 0;
  for (i = 0; i < BUFSIZE; ++i) {
    buf[i] = digits[i];
  }
  int l=strlen(buf);
  ...
}

BUFSIZE揮発性メモリの領域のサイズは次のとおりです。

揮発性メモリの構成方法によっては、単にループを使用するのではなく、コンテンツをコピーするために呼び出す必要があるルーチンがある場合があります。メモリで動作memcpyするように設計されていないため、動作しないことに注意してください。volatile

于 2012-11-29T12:58:02.783 に答える
5

コンパイラの警告は、strlen() がポインターを揮発性として扱わないことを意味するだけです。つまり、文字列の長さを計算するときにポインターをレジスターにキャッシュする可能性があります。私は、それは大丈夫だと思います。

一般にvolatile、コンパイラは変数をキャッシュしないことを意味します。この例を見てください:

extern int flag;
while (flag) { /* loop*/ }

flag != 0コンパイラは、フラグが別のスレッドのように「外部から」変更されていないと想定するため、これは永久にループします。他のスレッドの入力を待ちたい場合は、次のように書く必要があります。

extern volatile int flag;
while (flag) { /* loop*/ }

これで、コンパイラはループがループするたびに実際にフラグを調べます。これは、この例で意図した以上のものである必要があります。

あなたの質問への答え: 自分が何をしているのかわかっている場合は、 volatile を でキャストするだけですint l=strlen((char*)digits)

于 2012-11-29T12:55:05.097 に答える