4

今日、const識別子を使用しようとしましたが、const変数はまだ変更できることがわかり、混乱しています..

以下はコードです。compare(const void *a, const void *b) 関数で、 aが指している値を変更しようとしました。

#include <stdio.h>
#include <stdlib.h>

int values[] = {40, 10, 100, 90, 20, 25};

int compare (const void *a, const void*b)
{
    *(int*)a=2;
/* Then the value that a points to will be changed! */
    return ( *(int*)a - *(int*)b);
}

int main ()
{
    int n;
    qsort(values, 6, sizeof(int), compare);
    for (n = 0; n < 6; n++)
        printf("%d ", values[n]);
    return 0;
}

次に、 a自体の値も変更しようとしました。

#include <stdio.h>
#include <stdlib.h>

int values[] = {40, 10, 100, 90, 20, 25};

int compare (const void *a, const void*b)
{
    a=b;
    return ( *(int*)a - *(int*)b);
}

int main ()
{
    int n;
    qsort(values, 6, sizeof(int), compare);
    for (n = 0; n < 6; n++)
        printf("%d ", values[n]);
    return 0;
}

しかし、私はそれらの両方が機能することを発見しました.比較のパラメーターリストで const を使用する必要がある理由を誰かに説明してもらえますか?

4

4 に答える 4

6

この場合にのみ機能します。これは、作業しているポインターが元々一定ではなかったためです。constness をキャストしてから値を変更することは、未定義の動作です。UB は、アプリが成功からクラッシュまで何でもできることを意味し、紫色のドラゴンが鼻孔から飛び出します。

于 2012-05-04T21:09:04.937 に答える
3

間違いをしようと一生懸命努力するときではなく、ばかげた間違いからあなたを守ってくれます。それが悪い習慣である
(int *)a場合aは、代わりに使用してください。指している値だけがconstであるため、いつでも問題ありません。両方とも許可しない場合は、として宣言します。const something *(const int *)a
a = baconst void **a = xa = xaconst void * const

于 2012-05-04T21:11:46.617 に答える
2

ケース 1: constness をキャストするために静的キャストを使用しています。メソッドに対して定義された契約に違反しています。

ケース 2: (const である) a の内容を変更していませんが、const void ポインターを含む変数 a を割り当てています。

実用的な意味: ケース 1.) の場合、 a が実際に変数を指していない場合、自分自身を撃つことができます。

提案: 自分が何をしているのかを理解している場合にのみ constness を捨ててください。

于 2012-05-04T21:13:07.950 に答える
1

実際。

int compare (const void *a, const void*b);

ここで、考慮すべき点が 2 つあります。ポインタと、ポインタが指しているメモリ位置です。ポインタは一定ではありませんが、メモリの場所は一定です。

署名を次のように変更する場合:

int compare (const void *const a, const void *const void);

次に、すべてが const になります。あなたの場合、ポインターは変更できますが、値は変更できません。ポインタが別のメモリ位置を指すことができるようにします。

于 2012-05-04T21:13:32.437 に答える