[] 연산자 대신 포인터 산술을 통해 배열 요소에 액세스하는 것을 참조하는 것이 좋지 않습니까?


12

방금 C로 프로그래밍을 배우고 포인터와 배열에 대한 이해를 높이기 위해 포인터를 전혀 만들지 않고 배열의 요소를 참조하려고했습니다.

for(k1 = 0; k1 < ROW; k1++){
    for(k2 = 0; k2 < COLUMN; k2++){

        array[k1][k2] = k1*COLUMN + k2 + 1;

        printf("[%d][%d] = %d\n", k1, k2, *(array[k1] + k2));

    }
}

전체 코드는 완벽하게 컴파일되고 실행됩니다.

큰 소스 코드에서 모든 단일 배열에 대한 포인터를 작성하는 것이 매우 비효율적 인 것 같습니다.

따라서 포인터를 사용하여 배열의 주소를 저장하고 검색하는 대신 위에 표시된 것처럼 배열의 주소를 직접 사용하는 것은 좋지 않은 프로그래밍 방법입니까?


를 사용 printf "[%d][%d] = %d\n", k1, k2, array[k1] [k2]));하면 포인터 산술을 피할 수 있으며 이해하기 쉽습니다.
카스퍼 반 덴 버그

1
하하. 포인터와 배열의 작동 방식을 더 잘 이해하기 위해 실험으로 만했습니다.
Niko Gambt 2016

포인터 산술은 실제로 배열 인덱스를 사용하는 것보다 약 30 % 빠릅니다.
Andy

답변:


16

읽기 어려운 정도까지만 "나쁜"것입니다. a[x]와 동일 *(a+x)하므로 효율성이나 동작에 차이가 없습니다 (사실 x[a]작동합니다). 그것은 a[x]보통 우리 인간에게 훨씬 더 직관적입니다.

그러나 가독성이 중요하지 않다는 것은 아닙니다. 이 두 표현식을 코드에서 본다면 어떻게 "읽을"것인지 생각하십시오.

  • *(a+x)= "포인터 a와 정수 의 합이 가리키는 것 x"
  • a[x]= " x배열의 일원 a"

마찬가지로 배열 요소의 주소를 참조해야 할 경우 :

  • (a+x)= "포인터 a와 정수 의 합 x"
  • &a[x]= " x배열 의 th 멤버 주소 a"

대부분의 경우 []여러 배열 (특히 배열 배열)에서 작동하는 사소한 코드를 볼 때 버전을 이해하기가 더 쉽습니다. 이것이 []운영자가 처음에 존재하는 이유 입니다.

추신 : 학습 연습으로 이런 종류의 일을하는 것은 매우 좋은 생각입니다. 배열은 실제로 포인터와 오프셋이라는 것을 이해하는 것이 중요합니다.


이. 감사합니다. 방금 알고 싶은 것은 배열 요소의 주소를 참조 할 필요가있을 때, 다른 요소의 주소를 참조 해야하는지 여부, 여전히 나쁜지 여부를 알고 있습니다. 포인터를 사용하지 말고 대신 배열을 직접 사용하십시오. 이 질문은 정확히 지적하기 어려웠 기 때문에 OP에 입력하지 않은 이유입니다. 어쨌든, 내가 묻지 않았기 때문에 당신의 대답은 만족 스럽습니다.
Niko Gambt

1
@NikoGambt 당신은 항상 다른 질문을 할 수 있습니다 =)
Ixrec

1
그 정도 까지만 무슨 뜻 입니까? 프로그래밍 언어의 핵심은 사람이 쉽게 읽을 수있는 코드를 만드는 것입니다. 우리가 그것에 대해 신경 쓰지 않는다면, 우리는 모두 16 진수로 op 코드를 작성합니다.
Solomon Slow

2
배열은 포인터가 아니며 암시 적으로 포인터로 붕괴합니다.
코드 InChaos

4

예, 나쁜 습관이지만 비효율적 인 이유는 아닙니다.

배열 연산자는 후드 아래에서 포인터 산술을 사용하므로 동일하게 효율적입니다.

포인터 산술 문제는 오류가 발생하기 쉽고 읽기가 어렵다는 것입니다.

경험 법칙 : 필요하지 않은 경우 포인터 산술을 사용하지 마십시오.


1
어쨌든 포인터 산술을 사용하기 때문에 포인터가 오류가 발생하기 쉽고 읽기가 어렵다는 것을 의미하지 않습니까?
Niko Gambt

1
@NikoGambt 컴파일러는 후드 아래에서 포인터 산술을하는 데 능숙하며 '실수'를 거의하지 않습니다. 결과적으로 불쾌한 버그로 실수를 저지르는 것은 프로그래머입니다.
카스퍼 반 덴 버그

@KaspervandenBerg 예, 동의합니다. 그러나 프로그래머가 만든 오류에 관심이 있으며 배열 주소를 참조 해야하는 경우 위에서 수행 한 작업을 수행하는 것이 나쁜 프로그래밍 관행인지 확실하지 않습니다. 그러한 경우에 해당됩니다.
Niko Gambt

1
@NikoGambt 퍼포먼스 목적으로 읽기 어려운 것을 쓰는 것은 거의 항상 나쁜 습관이지만, 이득이없는 읽기 어려운 것을 쓰는 것은 명백한 나쁜 습관입니다.
Neil

@Neil 나의 작은 실험은 의미가 없습니다. 그렇게함으로써 컴파일러가 다차원 배열을 가리키는 포인터 배열을 만드는 것 같습니다. 그러나 가독성이 성능보다 중요하다고 말했기 때문에 여전히 프로그래밍 방법이 나쁜 것 같습니다.
Niko Gambt

0

당신의 학습 c를 식히십시오, 당신은 단지 작은 혀 꼬임 중 하나를 발견했습니다. 배열에서 포인터 산술을 수행하지 않고 포인터 배열을 수행하고 있습니다. 배열에서 포인터 산술을 수행 할 수 없습니다. 배열은 포인터로 붕괴하지만 포인터 자체는 아닙니다. 내가 가진 것은 (cmaster의 코멘트 참조)

int *array[]; //This is a array to pointers of type *int. 

array[k1] + k2; //This is pointer arithmetic on one pointer stored in the array  

이 포인터를 역 참조하면 방금 계산 한 포인터가 가리키는 값이 제공됩니다. 당신이하고있는 일을하는 데는 일반적으로 아무런 의미가 없습니다. 그러나 배열을 선형화 한 다음 이와 같은 보폭을 만들 수 있습니다.

int array[y_dim*x_dim]; 
int index = x_dim*y + x; 
array[index]; //Gives you the element in x, y!

그녀가 x_dim이라고 자처합니다. 내 대답이 명확 해지기를 바랍니다!


그것이 사용하는지 여부 그것은 OP에서 분명하지 않다 , 또는를 . 이 세 가지 정의 중 하나를 OP의 코드와 함께 사용할 수 있습니다. int* array[ROW];int array[ROW][COLUMN];int (*array)[COLUMN];
cmaster-복원 monica

예, 나는 그것을 알고 있습니다. 제 대답은 그 시점에서 약간 어색합니다. 고마워요!
fhtuft
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.