単項「&」オペランドとして左辺値が必要です

lvalue required as unary '&" operand


質問 written by bruno @2019-01-24 17:59:49Z

: 0 : 1 : 79

私のプロジェクトには問題があり、スレッドを使用してすべての行を加算してからすべてを合計するはずですが、単項「&」オペランドとして左辺値が必要であるというエラーが表示されます

pthread_create(&tid、NULL、&sum_line(0)、NULL);

いくつか試してみましたが、解決できませんでした、アイデアはありますか? ありがとう

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
static void * sum_line(int nr_line);

int Sum;
int A[4][4];

int main() {
  pthread_t tid;
  Sum=0;
  printf("\nOrig thread tid(%d) Sum=%d", pthread_self(), Sum);
  pthread_create(&tid, NULL, &sum_line(0), NULL);
  printf("\nChild thread was created tid(%d)", tid);
  pthread_join(tid,NULL);
  printf("\nOrig thread tid(%d)-->Child thread ended tid(%d) Sum=%d",pthread_self(), tid, Sum);
  printf("\n");

}

static void * sum_line(int nr_line) {
    int i;
    for(i=0;i<4;i++) {
        Sum=Sum+A[i];
        printf("\nChild thread tid(%d), i=%d, Sum=%d",pthread_self(),i,Sum);
        sleep(2);
    }
    printf("\nChild thread tid(%d)--> ending", pthread_self());
}
コメント 1

&sum_line(0) -これは何を与えることになっていますか?

written by ユージーンSh。 @2019-01-24 17:58:05Z

コメント 2

void * sum_line()returnステートメントがありませreturn

written by chux-モニカの復元 @2019-01-24 18:01:26Z

コメント 3

pthread_create(&tid, NULL, sum_line, (void*)0) 、これによりsum_lineが呼び出され、次の引数は同じ関数の最初の引数になります。int nr_line引数もvoid*として宣言し、値にキャストするのがおそらく最善です。

written by トラビスグリッグス @2019-01-24 18:04:21Z

回答 1 written by ジョナサン・レフラー @2019-01-24 18:12:50Z
2

関数へのポインタをpthread_create()渡します

&sum_line(0)ではなくsum_lineのみをsum_lineます。

pthread_create()関数は、関数を呼び出した結果ではなく、スレッド関数へのポインターpthread_create()つまり、関数名pthread_create()予期します。 pthread_create()関数は、新しいスレッドが関数を呼び出すように調整しますが、関数ポインターが必要です。

また、スレッド関数の署名は次のようにする必要があります。

void *function(void *arg);

また、関数は値を返す必要があります— return 0;追加しreturn 0; 閉じブレースの前。

NULLポインターを関数に渡します。 それがint nr_lineとして機能することは期待できません。 関数に番号を付けるには、いくつかの凝ったフットワークを行う必要があります。 主に2つのオプションがあります。

どちらか

Either

関数は次のようになります。

int nr_line = 247;

pthread_create(&tid, NULL, sum_line, &nr_line);

複数のスレッドを開始するときは、各スレッドが異なるオブジェクトへのポインターを取得するようにしてください。

または

void *sum_line(void *arg)
{
    int nr_line = *(int *)arg;
    …
    return 0;
}

または:

Just make sure each thread gets a pointer to a different object when you start multiple threads.

そして、関数は次のようになります:

Or

ダブルキャストは、異なるサイズの整数をポインターに変換することに関するコンパイラーの警告を回避します。

pthread_create()は、関数をvoid *function(void *args) pthread_create()ように呼び出すため、 (void (*)(void *))でキャストされていても、他のタイプの関数ポインターを渡すことに注意してください。未定義の動作につながります。

コメント 1

argを割り当ててsum_lineで与えたり解放したり、 intvoid *にキャストしたり逆にしたり(64bのoupps)したり、ローカル変数が消えるリスクを負わせたり(ここでは結合によって保護)することをお勧めします。ちょうど私の2セント;-)

written by ブルーノ @2019-01-24 18:11:54Z

コメント 2

@bruno —それに対処する多くの方法があります。私が概説したのは2つの受け入れ可能な方法(IMO)であり、複数のスレッドがそれぞれ別個の引数を取得することを確認することが重要であることに注意しました。割り当ては別のオプションです。必要なものではありません。たとえば、適切な型の配列であるローカル変数を使用し、配列の異なる要素へのポインターを各スレッドに渡すことが可能です。もちろん、変数の寿命が適切に尊重されていることを確認する必要があります-それは常に当てはまります。割り当てる場合は、解放する必要もあります。ここでは必要ありません。

written by ジョナサンレフラー @2019-01-24 18:15:47Z

コメント 3

たくさんの人がそのすべてを理解してくれることを願っています、多くの人が完全なコンテキストが同じかどうかを確認せずにコードをコピー/ペーストします、私は確かにあなたにそれを学習しません^^同じ価格で堅牢なコードを提案するにはmalloc&freeは何もありません)起こりうる将来の問題を制限します

written by ブルーノ @2019-01-24 18:29:47Z

コメント 4

私は自分でmalloc()free()使用しないので、通常は(ただし、コンテキストに依存しますfree() 、お勧めしません。私はそれが完全に可能であることを受け入れます。単一のスレッドを開始することは珍しいことsleep(2);特にスレッド関数にsleep(2);がある場合、「トレーニングの練習」を示しsleep(2);ループの途中で。提案された変更により、トレーニング演習が機能します。

written by ジョナサンレフラー @2019-01-24 18:33:12Z