프로그래밍

c언어 논리연산자 질문좀

6,7,8,9

 

풀이좀 알려줘라

 

특히  data 값이 왜 어떻게 나오는지 설명좀

 

답지 뒤에 있고

 

숙제아니고 독학중

282B460B-70F7-4330-BEDA-1B8BF2F89996.jpeg

38개의 댓글

2019.06.17

다쓰기 귀찮아 모르는것만 찝어바

0
@귀여운알파

7,8,9 번 데이터값이

어떻게 나오는지 궁금함

0
2019.06.17
@그림으로말해요

data 는 다 0이지

0
@귀여운알파

8 데이터값 5라고 되어잇는데??

왜 0으로 나옴??

0
2019.06.17
@귀여운알파

(data=0) 하게되면 data에 0이 대입되고 저 괄호 안의 식은 data의 값으로 평가되므로 연산할 때도 0으로 들어감

0
@귀여운알파

근데 위에서 int data = 5 라고 되어있는데?

1
2019.06.17
@그림으로말해요
[삭제 되었습니다]
@JohnTheSnow

그럼 답지가 잘못된거야??

0
@JohnTheSnow

답이

6. result = 0 data = 5

7. result = 0 data = 0

8. result = 0 data = 5

9. result = 0 data = 0

 

인데 왜 6,8 에서 data가 5나옴?

0

C기준으로.

대입 연산자 = 는 오른쪽에서 왼쪽으로 연산함.

논리 연산자 && ||는 왼쪽에서 오른쪽으로 넘어감

왼쪽에서 이미 조건을 충족해 버리면 오른쪽은 계산하지 않음. 즉 a&&b에서 a가 0(false)이면 b는 아예 제껴버려서 검토하지 않음. a||b에서 a가 1(true)이면 b는 검토하지 않음. 반대의 경우인 a&&b에서 a가 false라면 당연히 b를 확인해야 결과를 아니까 끝까지 실행되겠지. a||b에선 a가 false면 b도 확인할 거고.

 

따라서 6번 같은 경우 data!=5가 0이기 때문에 뒤에 있는 (data=0)을 검토하지 않기 때문에 data에 0을 대입하지 않아.

 

그래서 result = 0, data = 5가 됨.

 

이거 머리에 두고 있으면 뒤 7, 8도 풀릴테니 생략함. 그래도 모르겠으면 댓글로 다시 달아줘.

1
2019.06.17
@알파스트라이크

오 short circuit을 까먹고있었네. 세심하구만

0
@알파스트라이크

와 ㄹㅇ 개천재다

이제 이해됨

 

그리고 만약

data = 0 이면

--data 는 0나옴 -1나옴?

0
@그림으로말해요

6번식에서 data=0을 --data로 바꾼 경우를 말하는거야? result = data!=5&&(--data) 이거?

질문을 좀 더 정확하게 해줘.

 

0
@알파스트라이크

걍 이문제랑 별개로

 

int K = 0 이고

--K는 0이냐 -1이야?

0
@그림으로말해요

그냥

int k = 0;

--k;

를 말하는거면

k == -1;

 

int k = 0;

k--;

도 k == -1;

 

둘의 차이는 해당 식을 연산 하고 1을 감소시키느냐 식을 연산하기 전에 미리 감소시키느냐 차이임.

 

0
@알파스트라이크

이제 다 이해됨 ㄱㅅㄱㅅ

정말고맙다

디시에 가니 좆문가 새끼들밖에없던데 고맙다

진짜 이해됨

0
@그림으로말해요

아까 댓글단거 등록하려는데 없어서 여기다 추가로 달아줄게

 

 

8번의 경우는 설명 다 해준거 기억하면 응용할 수 있지.

result = result-- &&(data=0);

에서

result-- 부분을 체크하겠지? result==0인 상태에서 먼저 왼쪽을 체크하고 나서 1을 감소시켜서 result == -1을 만들려하겠지? 근데 체크하던 시점에선 result ==0이니까 전체식은 무조건 false임. 그래서 오른쪽 (data = 0)을 포함해서 이후 과정을 모두 제낌.

그리고 처음에 대입 연산자는 오른쪽에서 왼쪽으로 간다고 했지? false 즉 0을 이제 대입시키는 거지.

그 결과 result == 0이 되는거.

 

그래서 result는 0이고 data는 5인거

7번이랑 비슷하면서 결과가 전혀 다른게 그 때문임

7번은 &&의 왼쪽변을 판별하기 전에 --을 적용하기 때문에 true가 되서 오른쪽을 보는거고

8번은 &&의 왼쪽변을 먼저 판별하고 --을 적용하기 때문에 false가 되서 오른쪽을 안봄.

그리고 그 과정이 다 끝나고 나서 대입연산자 =에 의해 result 값을 마지막으로 대입시킴.

0
@알파스트라이크

그 논리를 몰랐음

and는 앞의 결과값이 먼저 0이면 뒤에값을 처리를 안하고 1이여만 뒤에값을 처리하고

 

or은 앞의 결과값이 1이면 뒤에값을 처리안하고

앞의 결과값이 0이여만 처리하는

논리를 몰랐다

어쨋든 완벽하게 이해됐어 정말고맙다

0
@그림으로말해요

ㅇㅇ 그부분은 보통 책에 설명이 되어 있는데 못보고 지나치거나 잘 생각 안나는 경우가 많지. 힘내

0
@알파스트라이크

읽었는데

자기가 직접 격지않으면

잘 안와닿더라

0
2019.06.17
@알파스트라이크

아 그걸 몰랏누 글쓴아 쏘리

0
2019.06.17

일단 이런 문제는 연산자 우선순위만 알면 쉽게 해결할 수 있지만 전위나 후위 (--, ++) 는 컴파일러마다 스펙이 다르기 때문에 조심해야 함.

data=0 처럼 쓰면 위 댓글에 적힌 일들이 일어나게 되고. data=0은 false니까

7번만 보자면 result = 4(--result) && 0. 결과는 false

result는 0 data는 0

0
@립톤티

?????

뭔가 너 잘못쓴거같다

0
2019.06.17

질문글 지울지도 모르니까 우선 박제.

0
@그는신이야

왜박제하는데?

0
2019.06.17
@그림으로말해요

프로그래밍 질문하고 지우는 악성유저가 많아서

0
2019.06.18

6번... 에??? 어리둥절...

계산기 만들 때 fifo로 만드는지, lifo로 만드는지에 따라서 계산 순서가 달라지는데,

고전적인 정석은 lifo라서 data에 0 넣고나서, 5랑 비교하면 true && false라서

result = 0, data = 0이 되는 것 같음.

fifo로 계산하면 5랑 비교하면 false고 뒤는 또 false임.

그럼 결과는 0,0 같음.

 

7번은 --먼저 계산하고, result = -1 && 0이므로,

역시 0,0

 

8번은 --를 뒤에 계산.

result = (false && 0) - 1 이므로 -1

data = 0

 

9번은 8번과 비슷.

result = (false || 0) - 1 이므로 -1

data = 0

0
@나혼자선다

6번은 data!=5가 false라서 && 뒤쪽 무시함. 고로 data=5 유지

0
2019.06.18
@중복은붐업부터박고시작

아하!

0
2019.06.18

?? 8번 9번 ub아님?

0
@아리성애자

&&과 ||는 C에서 보장된 시퀀스 포인트를 가지고 있음. 왼쪽의 피연산자 평가 직후에 해당함. 후위 증감 연산자인 ++와 --의 경우 저장된 값을 업데이트 하는 사이드이펙트는 이전 시퀀스 포인트와 그 다음 시퀀스 포인트 사이에 적용이 되어야 함. 따라서 &&연산자를 기준으로 그 왼쪽 피연산자(result--)에서 오른쪽 피연산자로 넘어가야 하는 과정에서 반드시 후위증감연산자 ++와 --의 업데이트가 발생해야함. 따라서 UB가 아님.

 

8번을 예로 들면 &&의 시퀀스 포인트 보장에 의해 좌변 평가 false -> --사이드 이펙트 적용 -> &&의 좌변 false에 의해 short circuit 적용

&&와 ||의 Short circuit의 경우 역시 C에서는 보장하고 있음.

 

다른 언어의 경우는 보장되지 않지만 이 경우는 C라서 UB가 아님.

 

반면

int cal(int a)

{

  a = 2 * a;

  return a;

}

 

int main (void) {

  int n=2;
  printf("%d  %d", n++, cal(n)); 

  return 0;
}

이 경우는 함수의 전달인자에서 n++, cal(n) 사이의 ,는 시퀀스 포인트가 아니며 둘 중 무엇을 먼저 평가할 지는 컴파일러 구현사항이므로 UB가 되겠지.

예를 들면 GCC(4.8.5기준)에서는 cal(n)부터 평가하고 n++을 평가한 후 후위연산 ++의 사이드이펙트 적용해서 값을 증가시킴(출력: 2 4)

MSVC(VS2010기준)에서는 n++평가하고 후위++의 사이드이펙트 적용하고 cal(n) 적용함.(출력: 2 6)

심지어 저 특성때문에 심지어 전위연산자를 써서 n++을 ++n으로 바꿔도 둘은 결과가 갈림 GCC는 3 4 VS는 3 6이 출력됨.

 

반면 위 문제 8, 9번의 경우 GCC, VS 둘 다 8번은 result는 0 data는 5 9번은 result는 0 data는 0으로 결과가 같음.

0
2019.06.18

이런 문제를 볼때마다 느끼는 건

이런 게 왜 필요하고 중요하냐는 거임.. 현직 개발자인데 진심 쓸모가 별루 없음..

게다가 저게 웃기는 게, 비주얼에서 저 코드 돌릴 때의 실제 값과, 리눅스 터미널에서 vi 편집기로 저 코드 돌릴 때의 값이 서로 다름..

니미..

0
@숨은음은

저기 나온 것들은 모두 gcc, msvc 모두 같은 값 나온다. UB에 걸리는 부분 없거든. 나름 문제자체는 그런 부분 생각하고 만들어진 문제임.

그리고 개인적으론 UB로 인한 실수 피하기 위해서 저런 연산자 정의되어 있는 행동 자체는 어떻게 작동하는지는 확실히 알고 가는게 좋다고 생각하기에 배울 땐 확실히 배우고 넘어가는게 좋다고 봄. 말하자면 지뢰가 뭔지 확실히 알아야 그 지뢰를 피할 수 있다고 생각해.

 

당장 여기만 해도 -- ++전후위 연산자에 대해 착각하고 있는 사람이 꽤 보이고 현업에서 UB 피하는 것을 당연하다고 생각하면서도 명확한 개념에서 혼동이 와서 간단해보이는 형태에서도 의외로 실수하는 경우가 심심찮게 보임.

 

물론 사용할 때 저렇게 가독성도 떨어지고 실수하기 좋은 형태로 사용하는건 반드시 피해야겠지.

0
2019.06.18
@알파스트라이크

똑같이 실제 코딩 해봐라 답 다르게 출력된다

다른건 몰라도 7번은

비주얼2017버전으로 돌리면 1 5

리눅스 터미널 gcc로 돌리면 0 0

으로 답 다르게 나온다

실제로 돌리고 올린 댓글임

0
@숨은음은

아니야 나도 둘다 돌려 봤어

리눅스 GCC(4.8.5) 비주얼 2010, 2017 셋 다 확인했고. 너 C로 작성한거 맞냐? 아니면 오타 있는거 아닌지 더블체크해라

그리고 하다못해 설령 UB가 걸린다고 해도 7번에서 1, 5가 나올 이유가 없는데? 증가 연산자도 아닌 감소연산자가 관여되어 있는 result가 1이란 건 무조건 뒤쪽 식이 검토된다는거고 검토되면 data가 5로 남아있을 수가 없어. C가 아니라도 절대 7번은 1 5가 못나와. 컴파일러가 정상이라면 어떤형태로 설계된 컴파일러라도 1 5는 나올 수가 없는게 7번 문제임.

0
@숨은음은

애초 MSVC 문서화부터 있는 && 설명을 보면

The first operand is completely evaluated and all side effects are completed before continuing evaluation of the logical AND expression.

 

The second operand is evaluated only if the first operand evaluates to true (nonzero). This evaluation eliminates needless evaluation of the second operand when the logical AND expression is false. You can use this short-circuit evaluation to prevent null-pointer dereferencing, as shown in the following example:

라고 되어 있어. 첫문장이 첫번째 식을 완전평가하고 사이드이펙트 적용하고 AND표기를 적용한다고 되어 있음. 그리고 두번째 문장은 다들 알고 있는 short circuit이고 따라서 7번이 0 0이 나오는게 정상임.

애초 저 두가지는 ISO C에 규격화되어 있는 부분이라 컴파일러 자체 구현사양이 아니야.

0
2019.06.18

저런 좆같은 수식좀 쓰지마 제발

0
2019.06.19

가끔 드는 생각이지만 이런 거 보다 보면

파이썬마냥 단항 증감 연산을 죽여버리는 게 낫지 않나 생각이 들 때가 있어

0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜 조회 수
180460 [모바일] 새 애플펜슬 나오면 기존 제품들 가격내려가? 2 II바II코II드II 0 1 시간 전 56
180459 [잡담] 드디어 왔다 레이니 1 ltearl 0 9 시간 전 154
180458 [프로그래밍] 그 혹시 게임쪽 종사자 있음? 12 god79ii 0 9 시간 전 231
180457 [컴퓨터] sata 케이블때문에 ssd가 망가질 수도 있나요? 8 드웨인토마스 0 10 시간 전 201
180456 [컴퓨터] 구글에서만 검색창 방향키가 안먹음 뒷북 0 13 시간 전 72
180455 [모바일] 횽들 어거좀 봐줘 6 부자가될개붕이놈들 0 14 시간 전 147
180454 [컴퓨터] 선생님들 혜안을 구합니다 9 빠른인정빌런 0 15 시간 전 138
180453 [모바일] 당근으로 갤럭시탭 s9 울트라 사기로했는데 2 말이야방구야 1 15 시간 전 224
180452 [모바일] 갤럭시 동영상 자르기 안되는 이유 아시는분?? 3 일토준지 0 15 시간 전 114
180451 [프로그래밍] 코린이 ㅅㅂ 뭐가 문젠지 모르겠어요 2 집에가게해줘 0 17 시간 전 231
180450 [컴퓨터] 해피해킹 키보드 회사서 못 쓰는 이유 3 닉네임변경후13일차 0 17 시간 전 298
180449 [컴퓨터] 컴 바꿧듬 10 탑똥 1 17 시간 전 128
180448 [컴퓨터] CPU 불량이 맞는가!? 14 꺄꺄룽 0 18 시간 전 176
180447 [정보] 최근에 꽤 핫했던 레노버 y700 2세대 정보 모음입니다. 13 SeraMint 2 18 시간 전 207
180446 [잡담] 님들 컴터 조립할 때 ㅈ같았던 경험들 있음? 4 UBCS 0 18 시간 전 131
180445 [컴퓨터] LG OLED티비쓰는데 HDMI로 컴연결해서 쓰거든 11 뚱땡보 0 19 시간 전 118
180444 [잡담] DDR5 삼성 시금치램에 방열판 달고싶은데 10 내일까지 0 19 시간 전 141
180443 [컴퓨터] 3.5mm 헤드셋을 연결했는데 마이크에서 스피커소리가 나옴..... 12 아건 0 20 시간 전 107
180442 [컴퓨터] 모니터 화이트스크린 심심할땐개드립 0 21 시간 전 45
180441 [모바일] 유튜브 뮤직 왜 안되는지 아는 사람?? 8 티탄즈 0 21 시간 전 149