programing

n이 상수 값인데 intx[n]가 잘못된 이유는 무엇입니까?

testmans 2023. 7. 29. 08:17
반응형

n이 상수 값인데 intx[n]가 잘못된 이유는 무엇입니까?

왜 이렇게 하는 것이 잘못된 것인지 이해할 수 없습니다.

const int n = 5; 
int x[n] = { 1,1,3,4,5 };

그럼에도 불구하고.n이미 상수 값입니다.

이것은 GNU 컴파일러에게 맞는 것처럼 보이지만,

const int n = 5;
int x[n]; /*without initialization*/

저는 C99의 VLA 기능에 대해 알고 있으며, 현재 진행 중인 것과 관련이 있다고 생각하지만, 배경에 대해 좀 더 명확한 설명이 필요합니다.

기억해야 할 중요한 것은const그리고 "감정"은 완전히 다른 두 가지를 의미합니다.

const키워드는 정말 "읽기 전용"을 의미합니다.상수는 다음과 같은 숫자 리터럴입니다.42또는1.5(또는 열거형 또는 문자 상수).상수 표현식은 컴파일 시 다음과 같이 평가할 수 있는 특정한 종류의 표현식입니다.2 + 2.

그래서 선언문이 주어지면,

const int n = 5;

그 표현n개체의 값을 나타내며 상수 식으로 처리되지 않습니다.일반적인 컴파일러는 다음에 대한 참조를 최적화합니다.n리터럴에 사용하는 것과 동일한 코드로 대체합니다.5그러나 이것은 필수 사항이 아니며, 표현식이 일정한지 여부에 대한 규칙은 현재 컴파일러의 영리함이 아니라 언어에 의해 결정됩니다.

사이의 차이에 대한 예const(읽기 전용) 상수(컴파일 시 계산됨)는 다음과 같습니다.

const size_t now = time(NULL);

const키워드는 값을 수정할 수 없음을 의미합니다.now초기화 후, 그러나 가치.time(NULL)실행 시간까지 계산할 수 없습니다.

그래서 이것은:

const int n = 5;
int x[n];

C에서 더 이상 유효하지 않은 것은 그것이 없는 것보다.const키워드

언어는 (그리고 아마도) IMHO가 평가해야 할 것입니다.n상수 식으로 정의되지 않을 뿐입니다. (C++에는 그러한 규칙이 있습니다. 자세한 내용은 C++ 표준 또는 적절한 참조 참조를 참조하십시오.)

값을 가진 명명된 상수를 원하는 경우5가장 일반적인 방법은 매크로를 정의하는 것입니다.

#define N 5
int x[N];

또 다른 접근법은 열거 상수를 정의하는 것입니다.

enum { n = 5 };
int x[n];

열거 상수는 상수 식이며 항상 유형입니다.int(즉, 이 방법은 다음 이외의 유형에서는 작동하지 않습니다.int) 그리고 그것은 거의 틀림없이 남용입니다.enum기계 장치

1999년 표준부터 어레이를 일정하지 않은 크기로 정의할 수 있습니다. 이는 VLA 또는 가변 길이 어레이입니다.이러한 배열은 블록 범위에서만 허용되며 이니셜라이저가 없을 수 있습니다(컴파일러가 이니셜라이저의 요소 수가 올바른지 확인할 수 없기 때문에).

하지만 당신의 원래 코드를 고려하면:

const int n = 5; 
int x[n] = { 1,1,3,4,5 };

컴파일러가 이니셜라이저에서 길이를 추론하도록 할 수 있습니다.

int x[] = { 1,1,3,4,5 };

그런 다음 어레이의 크기에서 길이를 계산할 수 있습니다.

const int x_len = sizeof x / sizeof x[0];

ㅠㅠint x[n]어디가 잘못되었습니까?n입니다.const 가치?

n상수가 아닙니다.const라고만 약속합니다.n프로그램 실행 중에는 수정할 수 없는 '읽기 전용' 변수입니다.
로 c에서는 c,const한정된 변수가 상수가 아닙니다.따라서 선언된 배열은 가변 길이 배열입니다.
Initializer 목록을 사용하여 가변 길이 배열을 초기화할 수 없습니다.

C11-§ 6.7.9/3:

초기화할 엔티티 유형은 크기를 알 수 없는 배열이거나 가변 길이 배열 유형이 아닌 전체 개체 유형이어야 합니다.

사용할 수 있습니다.#define또는enum만들기 위해서n

#define n 5
int x[n] = { 1,1,3,4,5 };   

배열을 완전히 초기화하는 경우 컴파일러가 배열 크기를 추론할 수 있도록 하는 것이 더 쉽고 안전하며 유지 관리가 가능합니다.

int x[] = { 1,1,3,4,5 };
const int n = sizeof(x) / sizeof(*x) ; 

그런 다음 배열 크기를 변경하려면 크기와 이니셜라이저 목록을 일치하도록 변경하지 않고 이니셜라이저 수만 변경하면 됩니다.이니셜이 많은 경우 특히 유용합니다.

그럼에도 불구하고.n입니다.constVLA를 생성하지 않는 한 어레이의 크기를 정의하는 데 사용할 수 없습니다.그러나 Initializer 목록을 사용하여 VLA를 초기화할 수는 없습니다.

매크로를 사용하여 고정 크기 배열을 만듭니다.

#define ARRAY_SIZE 5

int x[ARRAY_SIZE] = { 1,1,3,4,5 };

가 코가다의미다릅까니로으적음과드?와 의미적으로 요?myfunc()예외:

void myfunc(const int n) { 
    int x[n] = { 1,1,3,4,5 };
    printf("%d\n", x[n-1]);
    *( (int *) &n) = 17;    //  Somewhat less "constant" than hoped...
    return ;
}

int main(){
    myfunc(4);
    myfunc(5);
    myfunc(6);  //  Haven't actually tested this.  Boom?  Maybe just printf(noise)?
    return 0;
}

아이즈n정말 그 모든 상수?에 얼마나 많은 공간을 할당해야 한다고 합니까?x[](그렇게 하는 것이 컴파일러의 일이기 때문에)?

했듯이, 다른이지이듯, cv-qualifier 는const는 "컴파일 중 및 이후의 모든 시간에 대해 일정한 값"을 의미하지 않습니다.이는 "(가능하지만) 로컬 코드가 변경되어서는 안 되는 값"을 의미합니다.

언급URL : https://stackoverflow.com/questions/35162043/why-is-int-xn-wrong-where-n-is-a-const-value

반응형