형변환 미스테리..

cg3980의 이미지

char x = -128로 선언한 다음에

x를 1bit씩 출력하도록 하면
1000 0000으로 출력이 됩니다. 이건 문제가 안 되는데

근데 이걸 32bit를 출력하도록 해보면(함수를 작성)
1111 1111 1111 1111 1111 1111 1000 0000 이 됩니다.

근데 이걸 함수 인자로 -x를 넘겨주게 되면
0000 0000 0000 0000 0000 0000 1000 0000 이 됩니다.
-x로 변환한 다음엔 무슨 일이 일어나는건가요 내부에서?
제 추측은
1. 먼저 1000 0000 에서 1000 0000으로 변환(2의 보수)
2. 그다음에 singed int로 0을 붙임 -> 0000 0000 .... 0000 1000 0000
인것 같은데

왜 그냥 32bit로 출력하도록 하면 MSB가 확장되고
-x로 출력하도록 하면 위와같이 되는건가요?

void printInt(int x, int cnt) {
if (cnt < 32) printChar(x >> 1, cnt + 1);
cout << (x & 1);
}

int main(void)
{
ios::sync_with_stdio(false);
char x, y;
x = -128;

printInt((-x), 1); // 여기에 x를 넣으면 1111 ... 1000 0000이 되고 -x를 넣으면 0000 ... 0000 1000 0000이 됩니다.

return 0;
}

shint의 이미지

- 이 예제의 바이너리는. 왼쪽 부터. 순서입니다.

signed 예제
http://codepad.org/taxhzrs0

void printChar(char a, int n)
{
    cout << a << endl;
}
 
void printInt(int x, int cnt)
{
    if (cnt < 32)
    {
        printChar(x >> 1, cnt + 1);
    }
    else
    {
        cout << (x & 1);
    }
}
 
void fn_8bit(char x)
{
    cout << "fn_8bit(char x)" << "\t\t";
    int i;
    for(i=0; i<8; i++)
    {
        int d = (x >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bitChar(char x)
{
    cout << "fn_32bitChar(char x)" << "\t";
    int x32 = (int)x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bit(char x)
{
    cout << "fn_32bit(char x)" << "\t";
    int x32 = (int)x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bitNULL(char x)
{
    cout << "fn_32bitNULL(char x)" << "\t";
    int x32 = 0x00;
    x32 = (int)x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bit(int x32)
{
    cout << "fn_32bit(int x32)" << "\t";
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    char x, y;
 
    cout << "-128(x)" << endl;
    x = -128;
    fn_8bit(x);
    fn_32bitChar(x);
    fn_32bit(x);
    fn_32bitNULL(x);
    fn_32bit((int)x);
    cout << endl;
 
    cout << "+127(x)" << endl;
    x = 127;
    fn_8bit(x);
    fn_32bitChar(x);
    fn_32bit(x);
    fn_32bitNULL(x);
    fn_32bit((int)x);
    cout << endl;
 
 
    cout << "-128(-x)" << endl;
    x = -128;
    fn_8bit(-x);
    fn_32bitChar(-x);
    fn_32bit(-x);
    fn_32bitNULL(-x);
    fn_32bit((int)-x);
    cout << endl;
 
    cout << "+127(-x)" << endl;
    x = 127;
    fn_8bit(-x);
    fn_32bitChar(-x);
    fn_32bit(-x);
    fn_32bitNULL(-x);
    fn_32bit((int)x*-1);
    cout << endl;
 
 
    cout << "main() -128 fn_32bit(int x32)" << "\t";
    x = -128;
    int x32 = (int) -x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
 
 
    cout << "main() +127 fn_32bit(int x32)" << "\t";
    x = 127;
    x32 = (int) -x;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
 
    printInt((-x), 1); // 여기에 x를 넣으면 1111 ... 1000 0000이 되고 -x를 넣으면 0000 ... 0000 1000 0000이 됩니다.
 
    return 0;
}
 
//
-128(x)
fn_8bit(char x)		11111111
fn_32bitChar(char x)	11111111111111111111111111111111
fn_32bit(char x)	11111111111111111111111111111111
fn_32bitNULL(char x)	11111111111111111111111111111111
fn_32bit(int x32)	11111111111111111111111111111111
 
+127(x)
fn_8bit(char x)		11111110
fn_32bitChar(char x)	11111110000000000000000000000000
fn_32bit(char x)	11111110000000000000000000000000
fn_32bitNULL(char x)	11111110000000000000000000000000
fn_32bit(int x32)	11111110000000000000000000000000
 
-128(-x)
fn_8bit(char x)		11111111
fn_32bitChar(char x)	11111111111111111111111111111111
fn_32bit(int x32)	11111111000000000000000000000000
fn_32bitNULL(char x)	11111111111111111111111111111111
fn_32bit(int x32)	11111111000000000000000000000000
 
+127(-x)
fn_8bit(char x)		11111111
fn_32bitChar(char x)	11111111111111111111111111111111
fn_32bit(int x32)	11111111111111111111111111111111
fn_32bitNULL(char x)	11111111111111111111111111111111
fn_32bit(int x32)	11111111111111111111111111111111
 
main() -128 fn_32bit(int x32)	11111111000000000000000000000000
main() +127 fn_32bit(int x32)	11111111111111111111111111111111
�

unsigned 예제
http://codepad.org/PE8AusBJ

void printChar(char a, int n)
{
    cout << a << endl;
}
 
void printInt(int x, int cnt)
{
    if (cnt < 32)
    {
        printChar(x >> 1, cnt + 1);
    }
    else
    {
        cout << (x & 1);
    }
}
 
void fn_8bit(unsigned char x)
{
    cout << "fn_8bit(unsigned char x)" << "\t";
    int i;
    for(i=0; i<8; i++)
    {
        int d = (x >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bitChar(unsigned char x)
{
    cout << "fn_32bitChar(unsigned char x)" << "\t";
    unsigned int x32 = (unsigned int)x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bit(unsigned char x)
{
    cout << "fn_32bit(unsigned char x)" << "\t";
    unsigned int x32 = (unsigned int)x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bitNULL(unsigned char x)
{
    cout << "fn_32bitNULL(unsigned char x)" << "\t";
    unsigned int x32 = 0x00;
    x32 = (unsigned int)x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
void fn_32bit(unsigned int x32)
{
    cout << "fn_32bit(unsigned int x32)" << "\t";
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    unsigned char x, y;
 
    cout << "-128(x)" << endl;
    x = -128;
    fn_8bit(x);
    fn_32bitChar(x);
    fn_32bit(x);
    fn_32bitNULL(x);
    fn_32bit((unsigned int)x);
    cout << endl;
 
    cout << "+127(x)" << endl;
    x = 127;
    fn_8bit(x);
    fn_32bitChar(x);
    fn_32bit(x);
    fn_32bitNULL(x);
    fn_32bit((unsigned int)x);
    cout << endl;
 
 
    cout << "-128(-x)" << endl;
    x = -128;
    fn_8bit(-x);
    fn_32bitChar(-x);
    fn_32bit((unsigned int)-x);
    fn_32bitNULL(-x);
    fn_32bit((unsigned int)-x);
    cout << endl;
 
    cout << "+127(-x)" << endl;
    x = 127;
    fn_8bit(-x);
    fn_32bitChar(-x);
    fn_32bit((unsigned int)-x);
    fn_32bitNULL(-x);
    fn_32bit((unsigned int)x*-1);
    cout << endl;
 
 
    cout << "main() -128 fn_32bit(int x32)" << "\t";
    x = -128;
    unsigned int x32 = (int) -x;
    int i;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
 
 
    cout << "main() +127 fn_32bit(int x32)" << "\t";
    x = 127;
    x32 = (int) -x;
    for(i=0; i<32; i++)
    {
        int d = (x32 >> i) && 0x01;
        cout << d;
    }
    cout << endl;
 
    printInt((-x), 1); // 여기에 x를 넣으면 1111 ... 1000 0000이 되고 -x를 넣으면 0000 ... 0000 1000 0000이 됩니다.
 
    return 0;
}
 
//
-128(x)
fn_8bit(unsigned char x)	11111111
fn_32bitChar(unsigned char x)	11111111000000000000000000000000
fn_32bit(unsigned char x)	11111111000000000000000000000000
fn_32bitNULL(unsigned char x)	11111111000000000000000000000000
fn_32bit(unsigned int x32)	11111111000000000000000000000000
 
+127(x)
fn_8bit(unsigned char x)	11111110
fn_32bitChar(unsigned char x)	11111110000000000000000000000000
fn_32bit(unsigned char x)	11111110000000000000000000000000
fn_32bitNULL(unsigned char x)	11111110000000000000000000000000
fn_32bit(unsigned int x32)	11111110000000000000000000000000
 
-128(-x)
fn_8bit(unsigned char x)	11111111
fn_32bitChar(unsigned char x)	11111111000000000000000000000000
fn_32bit(unsigned int x32)	11111111111111111111111111111111
fn_32bitNULL(unsigned char x)	11111111000000000000000000000000
fn_32bit(unsigned int x32)	11111111111111111111111111111111
 
+127(-x)
fn_8bit(unsigned char x)	11111111
fn_32bitChar(unsigned char x)	11111111000000000000000000000000
fn_32bit(unsigned int x32)	11111111111111111111111111111111
fn_32bitNULL(unsigned char x)	11111111000000000000000000000000
fn_32bit(unsigned int x32)	11111111111111111111111111111111
 
main() -128 fn_32bit(int x32)	11111111111111111111111111111111
main() +127 fn_32bit(int x32)	11111111111111111111111111111111
�

//int binary c
C represent int in base 2 [duplicate]
https://stackoverflow.com/questions/6413956/c-represent-int-in-base-2

Can I use a binary literal in C or C++?
https://stackoverflow.com/questions/2611764/can-i-use-a-binary-literal-in-c-or-c

https://en.cppreference.com/w/cpp/io/manip/setbase

Macro BOOST_BINARY
https://www.boost.org/doc/libs/1_42_0/libs/utility/utility.htm#BOOST_BINARY

User-defined Literals
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2378.pdf

Decimal to binary in C
https://www.programmingsimplified.com/c/source-code/c-program-convert-decimal-to-binary

C Program to Convert Binary Number to Decimal and Decimal to Binary using fuction
http://letsdoprogramminginc.blogspot.com/2014/01/decimal-to-binary-converstion.html

10진수를 2로 나누기

Decimal to Binary Conversion
http://way2cplusplus.blogspot.com/2014/02/decimal-to-binary-conversion.html

----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.

매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.

각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com

익명 사용자의 이미지

이런식의 답변이 참.................

익명 사용자의 이미지

8비트 부호 있는 정수형(2의 보수)에 -128을 저장하고 그 부호를 바꾸려 해서는 안 됩니다.
표현 범위를 벗어나면서 미정의 동작을 일으킵니다.

구체적인 동작은 타겟 아키텍처와 컴파일러 및 최적화 수준에 따라 달라집니다.
지금 질문에 서술된 내용만으로는 알 수 없군요.

cg3980의 이미지

사실은 과제 내용이었어요. 물론 과제 해달란 건 아니고 이미 제출 제가 다 하고 뒤에 생각해보는데 잘 모르겠어서 올린 질문입니다. overflow를 일부러 일으킨 다음에 어떤 결과가 나오는지 예측해보라는 내용이었습니다.
이런건 어떤 키워드로 검색해야 하는지도 잘 모르겠네요.. 단순히 'type casting'이나 msb extension이라고 치면 c언어 기초적인 자료형 얘기만 나오는데 그런 수준의 내용을 원하는게 아니었어서..

익명 사용자의 이미지

https://kldp.org/comment/627283#comment-627283

위 스레드에서 C/C++의 signed integer와 관련된 undefined behavior가 보여줄 수 있는 괴현상을 맛보시기 바랍니다. :)
n1256 운운하는 답글은 제가 단 것입니다. 뭐 어차피 다 익명이라 믿거나 말거나.

프로그래밍 언어 활용을 배우는 측면에서 보면 undefined behavior를 만났을 때 더 이상 탐구할 의미는 없습니다. 어차피 일관성 없는 결과를 얻을 뿐이라서 무조건 피해야 하거든요.

반면에 컴파일러 최적화의 입장에서 보면 undefined behavior는 컴파일러에게 어느 정도의 자유를 허용해 주기 때문에, 재량껏 최적화에 최대한 유리한 방향으로 컴파일되는 경우가 많습니다. 물론 컴파일러에 따라, 최적화 옵션에 따라, 그리고 코드 맥락에 따라 달라질 수 있지요.

주어진 상황에서 컴파일러가 왜 이런 결과물을 만들었는지 추론해 보는 것도 재미있는 놀이가 될 겁니다. 물론 컴파일러 최적화 메커니즘에 대해 어느 정도 배경지식이 있어야 합니다.

익명 사용자의 이미지

-x 연산시에 어떤 일이 일어나는 지를 살펴보면
integer promotion 규칙에 따라, x의 타입이 char이므로 int로 변환합니다.
1000 0000 -> 1111 ... 1000 0000
- 연산을 수행합니다.
1111 ... 1000 0000 -> 0000 ... 1000 0000
printInt 함수의 파라미터 타입이 int이므로 더이상 변환할 필요는 없네요.

추가로 char 타입이 integer promotion이 일어날 때 signed int로 변환될지 unsigned int로 변환될지는 implementation에 따라 다릅니다. 이 경우는 signed int로 변환되는 시스템의 경우입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.