programing

C에서 sizeof 연산자는 2.5m를 넘으면 8바이트를 반환하지만 1.25m를 넘으면 4바이트를 반환합니다.* 2

firstcheck 2022. 7. 27. 21:48
반응형

C에서 sizeof 연산자는 2.5m를 넘으면 8바이트를 반환하지만 1.25m를 넘으면 4바이트를 반환합니다.* 2

는 왜 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★sizeof연산자는 다음 결과를 생성합니다.

sizeof( 2500000000 ) // => 8 (8 bytes).

... 8이 반환되며, 다음 작업을 수행하면 다음과 같이 반환됩니다.

sizeof( 1250000000 * 2 ) // => 4 (4 bytes).

8시 4분어떻게 하면sizeof표현식(또는 데이터 유형)의 크기를 결정하며, 특정 경우 이 문제가 발생하는 이유는 무엇입니까?

가 로는 ★★★★★★★★★★★★★★★★★★★★★★★.sizeof입니다.

바운티 질문:이러한 식을 평가하고 예상 출력을 생성할 수 있는 런타임 연산자가 있습니까(주조하지 않음).

2500000000 않다intlong (오류)long long 그 타입), '어느 쪽인가' 등). 1250000000,, 그렇기도 하다2에.sizeof 평가되지 않기 때문에 컴파일러는 곱셈이 에 맞지 않는다는 것을 알 수 없습니다.int 의 됩니다, , 、 [ ] 、 [ ] 、 [ ]의 사이즈가 반환됩니다.int.

되지 않은 동작)가 , 그 아마 '오버플로우'가 발생할 입니다.4.

여기:

#include <iostream>
int main()
{
    long long x = 1250000000 * 2;
    std::cout << x;
}

신은결 결과 ?측 ??? ???2500000000표현 유형입니다.1250000000 * 2int이기 int ★★★★★★★★★★★★★★★★★」int곱셈이 맞지 않으면 자동으로 더 큰 데이터 유형으로 승격되지 않습니다.

http://ideone.com/4Adf97

가 'Gcc라고 요.-1794967296단, 정의되지 않은 동작이기 때문에 임의의 수치로 할 수 있습니다.는 꼭 숫자입니다.int.

또한 피연산자 중 하나를 예상 유형으로 캐스트하면(정수가 아닌 결과를 찾는 경우 분할할 때 정수를 캐스트하는 경우와 거의 동일), 다음과 같이 동작합니다.

#include <iostream>
int main()
{
    long long x = (long long)1250000000 * 2;
    std::cout << x;
}

결과를 낳다2500000000.

[편집: 처음에는 C와 C++로 되어 있는 것을 눈치채지 못했습니다.C에 관해서만 대답하고 있습니다.]

"실행 시 식 또는 변수에 할당된 메모리 양을 결정할 방법이 있습니까?"음, 꼭 그렇진 않아요.문제는 이것이 매우 적절한 질문이 아니라는 것이다.

C-the-language의 「Expressions」(특정 실장과는 달리)는, 실제로는 메모리를 사용하지 않습니다(CPU 레지스터에 들어가는 결과의 수에 따라, 특정 실장에서는 계산을 보관 유지하는 코드나 데이터 메모리가 필요합니다).표현 결과가 변수에 저장되지 않으면 단순히 사라집니다(그리고 컴파일러는 저장되지 않은 결과를 계산하기 위해 런타임 코드를 생략할 수 있습니다).언어에서는 존재하지 않는 것, 즉 표현을 위한 저장 공간에 대해 질문할 방법이 없습니다.

반면 변수는 스토리지(메모리)를 차지합니다.변수 선언은 컴파일러에 얼마나 많은 저장 공간을 확보해야 하는지 알려줍니다.그러나 C99의 가변 길이 어레이를 제외하고 필요한 스토리지는 실행 시간이 아닌 컴파일 시에만 결정됩니다.이래서sizeof x는 「정수 표현」의 수 는 필요컴파일러는 (그리고 실제로) 의 값을 결정할 수 있습니다.sizeof x컴파일 시.

C99의 VLA는 이 규칙의 특별한 예외입니다.

void f(int n) {
    char buf[n];
    ...
}

★★★★★★에 필요한 buf는 컴파일러가 수 에 (는 없습니다sizeof buf는 컴파일 시간 상수가 아닙니다. 「」는,buf실제로 실행 시 할당되며 크기는 그때만 결정됩니다. ★★★★★★★★★★★★★★★★★.sizeof buf 는 런타임에 표시되는 표현입니다.

그러나 대부분의 경우 컴파일 시에 모든 것이 사전에 사이징되어 런타임에 식이 오버플로우하는 경우 유형에 따라 동작이 정의되지 않거나 구현 정의되거나 명확하게 정의됩니다. 서명된 오버플로우()INT_MAX27억을 조금 웃도는 수치로 "거짓말 행동"을 일으킵니다.부호 없는 정수는 모듈식 계산을 수행하므로 GF(2)로k 계산할 수 있습니다.

일부 계산이 오버플로하지 않도록 하려면 실행 시 직접 계산해야 합니다.이는 멀티 정밀도 라이브러리(gmp 등)를 C로 쓰기 어렵게 만드는 큰 부분입니다.일반적으로 어셈블리의 큰 부분을 코드화하고 CPU의 기존 속성(오버플로 플래그 또는 배폭 결과 레지스터 페어 등)을 활용하는 것이 훨씬 쉽고 빠릅니다.

Luchian은 이미 대답했습니다.그냥 완성하기 위해서...

C11 표준 상태(C++ 표준에는 유사한 행이 있음)는 유형을 지정하는 접미사가 없는 정수 리터럴의 유형을 다음과 같이 구분한다.

6.4.4 상수에서(C11 드래프트):

의미론

4 10진수의 값은 10진수의 값, 8진수의 값, 16진수의 값, 16진수의 값이다.어휘적으로 첫 번째 숫자가 가장 중요합니다.

5 정수 상수의 유형은 해당 값을 나타낼 수 있는 첫 번째 목록입니다.

표는 다음과 같습니다.

십진수 상수

int
int long int 
long long int

8진수 또는 16진수 상수

int
unsigned int
long int
unsigned long int
long long int
unsigned long long int

8진수 및 16진수 상수의 경우 부호 없는 유형도 사용할 수 있습니다.따라서 위의 목록(int, long int 또는 long long int) 중 가장 먼저 적합한 것은 플랫폼에 따라 정수 리터럴 타입이 됩니다.

또 다른 해답은 다음과 같이 말하는 것입니다.sizeof표현의 값이 아니라 유형입니다. sizeof유형 또는 식 중 하나로 설명할 수 있는 유형의 메모리 크기를 반환합니다.이 경우 컴파일러는 식을 실제로 계산하지 않고 컴파일 이 유형을 계산합니다(예를 들어 함수를 호출할 경우 결과 유형은 반환된 값의 유형입니다).

다른 포스터에서 설명한 것처럼 가변 길이 배열에는 예외가 있습니다(유형 크기는 런타임에만 알 수 있습니다).

즉, 당신은 보통 다음과 같은 것을 씁니다.sizeof(type)또는sizeof expressionexpression은 L-Value입니다.표현은 거의 결코 복잡한 컴퓨팅이 아닙니다(위의 함수를 호출하는 바보 같은 예처럼). 어쨌든 평가되지 않기 때문에 무용지물입니다.

#include <stdio.h>

int main(){
    struct Stype {
            int a;
    } svar;
    printf("size=%d\n", sizeof(struct Stype));
    printf("size=%d\n", sizeof svar);
    printf("size=%d\n", sizeof svar.a);
    printf("size=%d\n", sizeof(int));

}

또한 sizeof는 언어 키워드이므로 trailing expression 앞에 함수 괄호가 필요 없습니다(return 키워드에도 같은 종류의 규칙이 있습니다).

확인할 메일 질문에는 "연산자"가 없으며 식의 "컴파일 시간" 크기와 "실행 시간" 크기 사이에 차이가 없습니다.

특정 유형이 원하는 결과를 유지할 수 있는지 알고 싶다면 언제든지 다음과 같은 작업을 수행할 수 있습니다.

#include <stdio.h>
#include <limits.h>

int main(void) {
    int a = 1250000000;
    int b = 2;

    if ( (INT_MAX / (double) b) > a ) {
        printf("int is big enough for %d * %d\n", a, b);
    } else {
        printf("int is not big enough for %d * %d\n", a, b);
    }

    if ( (LONG_MAX / (double) b) > a ) {
        printf("long is big enough for %d * %d\n", a, b);
    } else {
        printf("long is not big enough for %d * %d\n", a, b);
    }

    return 0;
}

종달새에 대해서만 보다 일반적인 솔루션을 제공합니다.

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

/* 'gssim' is 'get size of signed integral multiplication */

size_t gssim(long long a, long long b);
int same_sign(long long a, long long b);

int main(void) {
    printf("size required for 127 * 1 is %zu\n", gssim(127, 1));
    printf("size required for 128 * 1 is %zu\n", gssim(128, 1));
    printf("size required for 129 * 1 is %zu\n", gssim(129, 1));
    printf("size required for 127 * -1 is %zu\n", gssim(127, -1));
    printf("size required for 128 * -1 is %zu\n", gssim(128, -1));
    printf("size required for 129 * -1 is %zu\n", gssim(129, -1));
    printf("size required for 32766 * 1 is %zu\n", gssim(32766, 1));
    printf("size required for 32767 * 1 is %zu\n", gssim(32767, 1));
    printf("size required for 32768 * 1 is %zu\n", gssim(32768, 1));
    printf("size required for -32767 * 1 is %zu\n", gssim(-32767, 1));
    printf("size required for -32768 * 1 is %zu\n", gssim(-32768, 1));
    printf("size required for -32769 * 1 is %zu\n", gssim(-32769, 1));
    printf("size required for 1000000000 * 2 is %zu\n", gssim(1000000000, 2));
    printf("size required for 1250000000 * 2 is %zu\n", gssim(1250000000, 2));

    return 0;
}

size_t gssim(long long a, long long b) {
    size_t ret_size;
    if ( same_sign(a, b) ) {
        if ( (CHAR_MAX / (long double) b) >= a ) {
            ret_size = 1;
        } else if ( (SHRT_MAX / (long double) b) >= a ) {
            ret_size = sizeof(short);
        } else if ( (INT_MAX / (long double) b) >= a ) {
            ret_size = sizeof(int);
        } else if ( (LONG_MAX / (long double) b) >= a ) {
            ret_size = sizeof(long);
        } else if ( (LLONG_MAX / (long double) b) >= a ) {
            ret_size = sizeof(long long);
        } else {
            ret_size = 0;
        }
    } else {
        if ( (SCHAR_MIN / (long double) llabs(b)) <= -llabs(a) ) {
            ret_size = 1;
        } else if ( (SHRT_MIN / (long double) llabs(b)) <= -llabs(a) ) {
            ret_size = sizeof(short);
        } else if ( (INT_MIN / (long double) llabs(b)) <= -llabs(a) ) {
            ret_size = sizeof(int);
        } else if ( (LONG_MIN / (long double) llabs(b)) <= -llabs(a) ) {
            ret_size = sizeof(long);
        } else if ( (LLONG_MIN / (long double) llabs(b)) <= -llabs(a) ) {
            ret_size = sizeof(long long);
        } else {
            ret_size = 0;
        }
    }
    return ret_size;
}

int same_sign(long long a, long long b) {
    if ( (a >= 0 && b >= 0) || (a <= 0 && b <= 0) ) {
        return 1;
    } else {
        return 0;
    }
}

출력은 다음과 같습니다.

size required for 127 * 1 is 1
size required for 128 * 1 is 2
size required for 129 * 1 is 2
size required for 127 * -1 is 1
size required for 128 * -1 is 1
size required for 129 * -1 is 2
size required for 32766 * 1 is 2
size required for 32767 * 1 is 2
size required for 32768 * 1 is 4
size required for -32767 * 1 is 2
size required for -32768 * 1 is 2
size required for -32769 * 1 is 4
size required for 1000000000 * 2 is 4
size required for 1250000000 * 2 is 8

네, sizeof()는 그 곱셈 결과에 필요한 메모리를 계산하지 않습니다.

두 번째 경우 양쪽 리터럴:1250000000그리고.2각각이 필요로 하는4 bytessizeof()가 반환됩니다.4. 값 중 하나가 위의 값일 경우4294967295 (2^32 - 1), 당신은 얻을 수 있었을 것입니다.8.

그러나 sizeof()가 어떻게 반환되었는지 모르겠다.8위해서2500000000. 다시 돌아오다4VS2012 컴파일러에서

C11 드래프트는 이쪽:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf Cx0 드래프트는 이쪽:http://c0x.coding-guidelines.com/6.5.3.4.html

어느 경우든 섹션 6.5.3.4를 찾고 있습니다.기본적으로 문제는 다음과 같습니다.

// Example 1:
long long x = 2500000000;
int size = sizeof(x); // returns 8

// Example 2:
int x = 1250000000;
int y = 2;
int size = sizeof(x * y); // returns 4

예 1에서는,long long(8 바이트)가 반환됩니다.예 2에서는, 다음과 같이 되어 있습니다.int * int이 경우,int(4 바이트가 반환됩니다).

현상금 질문에 답하려면:한마디로 이야기할 수 없군요. sizeof는 실행하려는 작업에 필요한 크기를 계산하지 않지만 적절한 라벨을 사용하여 작업을 수행한 경우 결과 크기를 알려줍니다.

long long x = 1250000000;
int y = 2;
int size = sizeof(x * y); // returns 8

// Alternatively
int size = sizeof(1250000000LL * 2); // returns 8

대량의 번호를 취급하고 있다고 말할 필요가 있습니다.그렇지 않으면 최소의 타입을 취급하고 있는 것으로 간주됩니다(이 경우는,int).

한 줄에서 가장 간단한 답은 다음과 같습니다.

sizeof()는 C타입의 입력이 C타입이며 값은 완전히 무시되는 컴파일 타임에서 평가되는 함수입니다.

상세: ..따라서 2500000000을 컴파일할 때 int에 넣기에는 너무 길기 때문에 LONG으로 저장해야 합니다.따라서 이 인수는 단순히 '(type) long'으로 컴파일됩니다.단, 1250000000과 2는 둘 다 타입 'int'에 들어맞기 때문에 사이즈가 전달되는 타입입니다.컴파일러가 단순히 타입에 관심이 있기 때문에 결과값은 저장되지 않기 때문에 곱셈은 평가되지 않습니다.

언급URL : https://stackoverflow.com/questions/16828006/in-c-sizeof-operator-returns-8-bytes-when-passing-2-5m-but-4-bytes-when-passing

반응형