programing

한 줄에 여러 개의 할당

coolbiz 2023. 9. 7. 22:11
반응형

한 줄에 여러 개의 할당

방금 임베디드 c(dsPIC33)에 있는 문구를 발견했습니다.

sample1 = sample2 = 0;

이것이 의미할까요?

sample1 = 0;

sample2 = 0;

왜 이런 식으로 타자를 치는 거지?이것은 좋은 코딩입니까 나쁜 코딩입니까?

과제는 오른쪽에서 왼쪽으로 수행되며, 이들은 정상적인 표현임을 기억해야 합니다.그래서 컴파일러들의 관점에서 볼 때는

sample1 = sample2 = 0;

와 같음

sample1 = (sample2 = 0);

와 같은.

sample2 = 0;
sample1 = sample2;

은,sample2 0된우이우된sample1음이됩니다 됩니다.sample2처럼 둘 다 하는 것과 . 실제로는 추측한 대로 둘 다 0에 할당하는 것과 같습니다.

두 에 대해 으로 의 의 t그리고.uT그리고.U각각과

T t;
U u;

숙제

t = u = X;

(where)Xvalue)는 is some value)로 됩니다.

t = (u = X);

그리고 한 쌍의 독립적인 과제에 해당합니다.

u = X;
t = (U) X;

의 에 하십시오 하십시오의 합니다.X는 변수에할다e에 도달할 으로 예상됩니다.t"" 그것이 처럼""를한 것처럼u첫째, 하지만 말 그대로 그렇게 될 필요는 없습니다.X히은로야다과fe으로 유형으로 변환하면 됩니다.ut은 . 을 에 할 가 에 .u에에서 했습니다.ut의 두 순서가 있지 어떤 수 있는데, 는 즉, 의 가 로도 합니다 을 은 은 합니다 을 은 의

t = (U) X;
u = X;

는 또한 이 식을 위한 유효한 실행 스케줄입니다. (이 시퀀스 자유는 할당의 결과가 r값에 있는 C 언어에 특정적입니다.C++에서 할당은 모든 값으로 평가되며, 이를 위해서는 "연쇄된" 할당이 순차적으로 수행되어야 합니다.)

더 많은 맥락을 보지 않고서는 그것이 좋은 프로그램 연습인지 나쁜 프로그램 연습인지 말할 수 없습니다.가 서로 되어 있는 예:두가로게는우어예(우예는두:n어(가esen :x그리고.y포인트의 좌표), "연쇄된" 과제를 사용하여 공통적인 가치로 설정하는 것은 실제로 완벽하게 좋은 연습입니다(저는 심지어 "권장 연습"이라고 말하고 싶습니다).그러나 변수가 완전히 관련이 없는 경우에는 단일 "연쇄된" 할당에 변수를 혼합하는 것은 결코 좋은 생각이 아닙니다.특히 이 변수들이 서로 다른 유형을 가지고 있어서 의도하지 않은 결과를 초래할 수 있습니다.

C언어는 실제 조립목록 없이 좋은 답이 없다고 생각합니다 :)

단순한 프로그램의 경우:

int main() {
        int a, b, c, d;
        a = b = c = d = 0;
        return a;
}

는 이 어셈블리(Kubuntu, 4(Kubuntu, gcc 4.8.2, x86_64)가 있습니다.-O0션론 ; )

main:
        pushq   %rbp
        movq    %rsp, %rbp

        movl    $0, -16(%rbp)       ; d = 0
        movl    -16(%rbp), %eax     ; 

        movl    %eax, -12(%rbp)     ; c = d
        movl    -12(%rbp), %eax     ;

        movl    %eax, -8(%rbp)      ; b = c
        movl    -8(%rbp), %eax      ;

        movl    %eax, -4(%rbp)      ; a = b
        movl    -4(%rbp), %eax      ;

        popq    %rbp

        ret                         ; return %eax, ie. a

그래서 gcc는 실제로 모든 것을 연결하고 있습니다.

sample1 = sample2 = 0;

과연

sample1 = 0;
sample2 = 0;  

에 그리고 만일에 한 sample2이는 앞서 선언한 바 있습니다.
런로면안요요안면u로런:ys'ton요 .

int sample1 = sample2 = 0; //sample1 must be declared before assigning 0 to it

이런 코딩 방식이 좋든 나쁘든 스스로 결정할 수 있습니다.

  1. IDE에서 다음 줄에 대한 조립 코드를 보기만 하면 됩니다.

  2. 그런 다음 코드를 두 개의 개별 할당으로 변경하고 차이점을 확인합니다.

이 외에도 컴파일러에서 최적화(크기 및 속도 최적화 모두)를 해제/설정하여 어셈블리 코드에 어떤 영향을 미치는지 확인할 수도 있습니다.

결과는 같습니다.어떤 사람들은 과제가 모두 같은 값이면 과제를 연결하는 것을 선호합니다.이 접근법에는 아무 문제가 없습니다.개인적으로, 저는 변수들이 밀접한 의미를 가진다면 이것이 더 좋다고 생각합니다.

다른 사람들이 말했듯이, 이것이 실행되는 순서는 결정적입니다.= 연산자의 연산자 우선 순위이것이 오른쪽에서 왼쪽으로 실행된다는 것을 보장합니다.즉, 샘플 2가 샘플 1 이전의 값을 제공받음을 보장합니다.

그러나 하나의 행에 여러 개의 할당을 하는 것은 잘못된 관행이며 많은 코딩 표준(*)에서 금지하고 있습니다.첫째, 특별히 읽을 수 있는 것이 아닙니다(아니면 이 질문을 하지 않을 것입니다).둘째, 위험합니다.예를 들면.

sample1 = func() + (sample2 = func());

그러면 연산자 우선 순위는 이전과 동일한 실행 순서를 보장합니다(+). =보다 높은 우선 순위를 가지므로 괄호가 됩니다.sample2는 sample1보다 먼저 값이 할당됩니다.그러나 사업자 우선순위와 달리 사업자의 평가순서는 결정적인 것이 아니라 불특정 행위입니다.가장 오른쪽에 있는 함수 호출이 가장 왼쪽에 있는 함수 호출보다 먼저 평가된다는 것을 알 수 없습니다.

컴파일러는 위의 내용을 자유롭게 기계 코드로 번역할 수 있습니다.

int tmp1 = func();
int tmp2 = func();
sample2 = tmp2;
sample1 = tmp1 + tmp2;

코드가 func()가 특정 순서로 실행되는 것에 의존한다면, 우리는 고약한 버그를 만든 것입니다.프로그램의 한 곳에서는 정상적으로 작동할 수 있지만, 코드가 동일하더라도 동일한 프로그램의 다른 부분에서는 중단됩니다.컴파일러는 하위 표현을 원하는 순서대로 자유롭게 평가할 수 있기 때문입니다.


(*) MISRA-C:2004 12.2, MISRA-C:2012 13.4, CERT-C EXP10-C.

앞서 본 바와 같이,

sample1 = sample2 = 0;

와 같음

sample2 = 0;
sample1 = sample2;

문제는 riscy가 레지스터를 직접 구동하는 데 자주 사용되는 임베디드 c에 대해 문의했다는 것입니다.많은 마이크로컨트롤러의 레지스터는 읽기 및 쓰기 작업에 다른 목적을 가지고 있습니다.따라서, 일반적인 경우에는, 다음과 같지 않습니다.

sample2 = 0;
sample1 = 0;

예를 들어 UDR을 UART 데이터 레지스터라고 합니다.UDR에서 읽는 것은 입력 버퍼에서 받은 값을 얻는 것을 의미하고 UDR에 쓰는 것은 전송 버퍼에 원하는 값을 넣고 통신을 치는 것을 의미합니다.그런 경우에는.

sample = UDR = 0;

합니다. 합니다(을 합니다 하여 a) UART 의 을 합니다 를 합니다 을 하여 ( )UDR = 0;및 b)를 ) b) 를 합니다 를 합니다 를 를 sample값을 매깁니다.sample = UDR;).

임베디드 시스템의 동작은 코드 작성자가 예상하는 것보다 훨씬 복잡할 수 있습니다.MCU를 프로그래밍할 때는 이 표기법을 주의 깊게 사용하십시오.

이 특수한 경우를 처리하십시오... b가 형태의 구조의 배열이라고 가정합니다.

{
    int foo;
}

그리고 나를 b의 오프셋이 되게 해주세요.int를 반환하고 배열 b의 재할당을 수행하는 함수 realoc_b()를 고려합니다.다음과 같은 다중 할당을 고려합니다.

a = (b + i)->foo = realoc_b();

내 경험으로는 (b + i)가 먼저 해결된 후 RAM에서 b_i라고 가정하고 realoc_b()가 실행됩니다.RAM에서 realoc_b()가 변경되면 b_i가 더 이상 할당되지 않습니다.

변수 a는 잘 할당되었지만 (b + i)->foo는 할당의 가장 왼쪽 항, 즉 realoc_b()의 실행에 의해 b가 변경되었기 때문이 아닙니다.

이로 인해 b_i가 할당되지 않은 RAM 위치에 있을 가능성이 있으므로 분할 오류가 발생할 수 있습니다.

버그가 없고 (b + i) -> foo가 a와 같으려면 한 줄 할당을 두 개의 할당으로 분할해야 합니다.

a = reallocB();
(b + i)->foo = a;

코딩 스타일 및 다양한 코딩 권장 사항은 여기를 참조하십시오. 가독성 a=b=c 또는 a=c; b=c;?

나는 그것을 사용하는 것으로 믿습니다.

sample1 = sample2 = 0;

일부 컴파일러는 2개의 할당에 비해 약간 더 빠른 어셈블리를 생성합니다.

sample1 = 0;
sample2 = 0;

0이 아닌 값으로 초기화하는 경우 특히 그렇습니다.다중 할당의 의미는 다음과 같습니다.

sample2 = 0; 
sample1 = sample2;

따라서 2개의 초기화 대신 1개와 1개의 복사만 수행합니다.속도 상승(있는 경우)은 매우 작지만 내장된 경우에는 모든 작은 비트가 중요합니다!

언급URL : https://stackoverflow.com/questions/19353686/multiple-assignment-in-one-line

반응형