C언어 bit연산 질문입니다.

choboja의 이미지

C언어 비트연산 질문입니다.
일단 첫번째 출력은 0xffffffffffffffff 이구요.
제가 원한 두번째 출력은 64bit 를 모두 left shift시키니 0을 예상했는데,
두번째 출력역시 0xffffffffffffffff 나오는군요.

원래 C언어의 shift는 0을 패딩하지 않나요?
왜 이런 결과가 나오는걸까요?
답변 부탁드릴께요.

#define ALL_SET_BIT                (0-1UL)
 
int main()
{
    unsigned long long down_side = 0;
    down_side = ALL_SET_BIT;
 
    printf("%llx\n", down_side);
 
    printf("%llx\n", down_side << 64);
 
 
    return 0;
 
}

terzeron의 이미지

64비트를 shift해서 그런 것 같습니다. 잘못된 실행이라고 간주해버리는 거죠. (compile-time warning 발생합니다.)
32비트나 63비트만 shift해보시죠.

choboja의 이미지

64보다 작은 수를 shift시에는 정상 동작합니다.
하지만 64의 배수면 위와 같은 상황이 발생하네요.

일단 이런식으로 사용을 하고 있는데, 이유를 알고싶네요.

    printf("%llx\n", down_side <<= 63);
    printf("%llx\n", down_side <<= 1);

bushi의 이미지

맞는 지 틀린 지는 직접 찾아보세요.
주워 들은 것만 옮깁니다.

C 의 경우 n bit 에 대한 shift 연산은 n-1 까지만 유효합니다.
그 이상은 undefined 입니다.
컴파일러 제작자가 심혈을 기울여 모든 예외처리를 해 줄 수도 있고,
그냥 CPU 에게 던져버리고 신경쓰지 않을 수도 있습니다.

x86 의 경우 5bit 혹은 6bit 를 mask 해서 사용합니다.

쿨한 컴파일러가 x86 에게 던져주고 신경 끈 경우라면,
64 건 128 이건 0 과 동일한 결과를 보게 되실겁니다.
65 건 129 이건 1 과 동일한 결과를 보게 되실거고요.

drinkme의 이미지

원인은 x86의 SHL명령에 있지 싶습니다.
http://www.vikaskumar.org/amd64/bitshift.htm

보시면,
shift 명령시에 count에 해당되는 CL값이
32bit에서는 하위 5bit만, 64bit에서는 하위 6bit만 사용되도록 mask된다는 것입니다.

그래서,
down_side << 64

down_side << (64 & 0x3F)

이렇게 되는거죠.

cinsk의 이미지

언어 정의에, 해당 타입의 비트 수보다 작은 수치만큼만 shift가 가능하다고 나와 있습니다.

6.5.7.3 ...The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

필요시 CHAR_BIT 매크로를 써보기 바랍니다. 예를 들면 "something << (CHAR_BIT * sizeof(long) - 1)" 꼴로...

colso11의 이미지

부호비트에 1로 셋팅 된 변수를 left로 shift하면 무조건 맨 오른쪽 비트는 1로 셋팅 된다고 알고 있습니다.

즉 비트가

01234567......63 위치
11111111.......1

로 되어 있고 왼쪽으로 시프트 하면

.........01234567........63
1 <-- 11111111........1
↑0번째 bit

이렇게 된다고 합니다.

C언어 책에서 본 건데 C언어가 컴파일러 마다 달리 동작하겠지만 뭐 그렇게 동작한다고 하더군요.

당신 무엇을 아는가?
난 아무것도 모르네;;;;

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.