6

申し訳ありませんが、別のCポインタの質問です。配列を並べ替えて最大と最小の整数を取得する関数func()があります。それらをmain()のポインター変数内に配置しようとしていますが、値はfunc()関数内でのみ正しいです。理由がわかりません:(

#include <stdio.h>

void func(int arr[], int *s, int *l, int n){
    int i = 1;
    for(; i < n; i++){
        int temp = arr[i];
        int n = i;
        while( n > 0 && arr[n-1] > temp){
            arr[n] = arr[n-1];
            n--;
        }
        arr[n] = temp;
    }
    l = &arr[n-1];
    s = &arr[0];\
    printf("%d %d\n",*l,*s);
}

int main(void){
    int arr[] = {1,2,9,3,58,21,4};
    int *s, *l;
    int size = 7;
    func(arr,s,l,size);
    printf("%d %d\n",*l,*s);
} 
4

3 に答える 3

10

Cの関数に引数としてポインターを渡すと、ポインターのコピーが作成されます。したがって、ポインタの値を変更しても、その関数以外では効果がありません。ただし、ポインタによって参照されるメモリの値を変更すると、必要に応じてどこでも有効になります。あなたの場合、あなたはこれをする必要があるでしょう:

void func(int arr[], int *s, int *l, int n){
    // sorting code..
    // l = &arr[n-1]; WRONG - these change the value of the pointer,
    //s = &arr[0];\   without changing the value of the memory they reference

    *l = arr[n-1]; // CORRECT - changes the value at the referenced memory
    *s = arr[0];
    printf("%d %d\n",*l,*s);
}

もちろん、ポインタの使用方法mainも正しくありません。それらは初期化されておらず、セグメンテーション違反を引き起こす可能性があります。int*そこでは通常の変数よりも実際の変数を使用する理由がないように思われるのでint、「参照によって」それらを渡すために別のアプローチを取ることができます。

int main(void){
    int arr[] = {1,2,9,3,58,21,4};
    // int *s, *l; WRONG - we don't need pointers, we need to pass regular ints
    int s, l;
    int size = 7;
    // Get the address of our variables with the address-of (&) operator
    // This effectively creates int* variables out of our int variables
    func(arr, &s, &l,size);
    printf("%d %d\n",*l,*s);
} 

ここでの「参照による」という用語は、変数に関連付けられたアドレスのコピーをまだ受け取っているため、フレーズの本当の意味では正しくないことに注意してください。ほとんどの言語は、この区別を取り除き、変数とその値へのアクセスのみを許可することにより、真の参照機能を提供します。コピーは、プログラマーの目には見えません。これは、呼び出された関数によって値が変化する可能性があるという意味で、「参照lおよびs内部」であると考えることができます。main

于 2012-11-14T15:47:48.310 に答える
5

ポインター変数が指しているものを変更する場合は、ポインター変数のアドレスを渡す必要があります。そうしないと、ポインター変数のコピーが関数内で変更されます(これが関数内で正しい理由です)。

void func(int arr[], int** s, int** l, int n){
    /* snip */

    *l = &arr[n-1];
    *s = &arr[0];
}

func(arr, &s, &l, size);

これにより、配列の要素が残りs、ポイントされます。整数の値が必要な場合は、変数を定義してそのアドレスを配列に渡し、関連する値を配列からコピーすることもできます。larrintmain()func()

void func(int arr[], int* s, int* l, int n){
    /* snip */

    *l = arr[n-1];
    *s = arr[0];
}

int s, l;
func(arr, &s, &l, size);

CFAQからこの質問を参照してください。

于 2012-11-14T15:46:18.423 に答える
1

ポインタが初期化されていません。2つの解決策があります。

  • 関数で整数を使用しmainます(最終的には、役に立たないものの、ポインターが同じ関数で整数を指すようにします)。
  • ポインタに動的にメモリを割り当てます。

最も簡単なコード:

#include <stdio.h>

int main(void)
{
    int arr[] = {1, 2, 9, 3, 58, 21, 4};
    int s, l;
    int size = 7;
    func(arr, &s, &l, size);
    printf("%d %d\n", l, s);
} 

現在のコードでは、配列の大文字と小文字を区別して指定lする必要はありません。sしたがって、Dan Fが述べたように、整数の割り当てを行うことができます。

void func(int arr[], int *s, int *l, int n)
{
    int i = 1;
    for(; i < n; i++){
        int temp = arr[i];
        int n = i;
        while( n > 0 && arr[n-1] > temp){
            arr[n] = arr[n-1];
            n--;
        }
        arr[n] = temp;
    }
    *l = arr[n-1];
    *s = arr[0];
    printf("%d %d\n", *l, *s);
}
于 2012-11-14T15:43:31.440 に答える