Soru İnt x neden n n bir const değeridir?


Bunun neden yanlış olduğunu anlayamıyorum:

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

buna rağmen n zaten bir const değeridir.

Bunu yaparken GNU derleyicisi için doğru gibi görünüyor:

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

C99'un VLA özelliğinin farkındayım ve bunun neler olduğunu anladım ama Arka planda neler olup bittiğine dair bazı açıklamalara ihtiyacım var.


37
2018-02-02 19:19


Menşei


Takılırsan şüpheliyim static tanımı üzerine n, Çalışacak; static const depolanmış sabit değil, gerçek bir global derleme zamanı sabiti olurdu. - ShadowRanger
@ShadowRanger: C, C ++ değil. Semantiği const farklılıklar biridir. C'nin sembolik sabiti yoktur. Örneğin. 1 bir tamsayı sabiti C standardından itibaren. const int i hala değişken! - too honest for this site
const sadece bir söz sen Derleyiciye, bir değişkeni doğrudan ya da dolaylı olarak değiştirmeyeceksiniz. İlk çoğu derleyicinin uyarması için, ikincisi için (örneğin, işaretçiler aracılığıyla) olası tüm ihlalleri tespit etmede çok sınırlı kalmaktadırlar. Sözleşmeyi ihlal ederseniz, tanımlanmamış davranışları çağırırsınız. - too honest for this site
@Olaf, C var bazı belki de onları beklemeyeceğiniz sembolik sabitler, yani numaralandırmalar. - Jens Gustedt
@JensGustedt: Evet, bunları her zaman unutuyorum. Bazı özel türlerdir, çünkü çoğunlukla türlerini açıkça belirleyemezsiniz (C11'in C ++ 11'den kopyalanmış olması gerekir) enumSonunda yararlıdır. Ve iki "boolean" sabiti _True ve _False kullanıcı tanımlı değil. Hmm, yazdığın gibi, yani başkalarının da var olduğunu ima ettiğin gibi: unuttum diğer kullanıcı tanımlı sembolik sabitler? (ciddi soru, basit bir şeyi gözden kaçırmış olabilirim - eğer ormanda iseniz, sadece ağaçları görürsünüz) - too honest for this site


Cevaplar:


Hatırlanması gereken en önemli şey const ve "sabit" iki farklı şeyi ifade eder.

const anahtar kelime gerçekten "salt okunur" anlamına gelir. bir sabit gibi sayısal bir değişmezdir 42 veya 1.5 (veya bir numaralandırma veya karakter sabiti). bir sabit ifade gibi derleme zamanında değerlendirilebilen belirli bir ifade türüdür 2 + 2.

Yani bir beyanname verildi:

const int n = 5;

ifade n değerinin nesneve sürekli bir ifade olarak ele alınmaz. Tipik bir derleyici, bir başvuruyu optimize eder n, bir değişmez için kullanacağı aynı kodla değiştirilmesi 5Ancak bu gerekli değildir - ve bir ifadenin olup olmadığı sabit Mevcut derleyicinin zekiliği tarafından değil, dil tarafından belirlenir.

Arasındaki farkın bir örneği const (salt okunur) ve sabit (derleme zamanında değerlendirilir):

const size_t now = time(NULL);

const anahtar kelime, değerin değiştirilmesine izin verilmediğini gösterir now onun başlatılmasından sonra, ama değeri time(NULL) çalışma zamanına kadar açık bir şekilde hesaplanamaz.

Yani bu:

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

C'den daha geçerli değildir. const Anahtar kelime.

Dil could (ve IMHO muhtemelen olmalı) değerlendirmek n sabit bir ifade olarak; sadece bu şekilde tanımlanmadı. (C ++ böyle bir kuralı vardır; C ++ standardına veya gory detayları için iyi bir referansa bakın.)

Değerle adlandırılmış bir sabit isterseniz 5En yaygın yol bir makro tanımlamaktır:

#define N 5
int x[N];

Başka bir yaklaşım, bir numaralandırma sabitini tanımlamaktır:

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

Numaralandırma sabitleri sabit ifadelerdir ve her zaman int (Bu yöntem, başka türler için çalışmaz anlamına gelir int). Ve muhtemelen bir kötüye kullanımı enum mekanizması.

1999 standardından başlayarak, sabit olmayan bir boyutla bir dizi tanımlanabilir; Bu bir VLA veya değişken uzunluklu dizidir. Bu tür dizilere yalnızca blok kapsamında izin verilir ve başlatıcılar olmayabilir (çünkü derleyici, başlatıcının doğru sayıda öğeye sahip olduğunu kontrol edemediği için).

Ancak orijinal kodunuz verildiğinde:

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

Derleyicinin, başlatıcıdan uzunluğu çıkarmasına izin verebilirsiniz:

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

Ve sonra uzunluğu dizinin boyutundan hesaplayabilirsiniz:

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

35
2018-02-02 21:43



"Bir sabit bir sayısal değişmezdir". Bu kesinlikle doğru mu? Diğer bazı sabitler olmalı? - artm
OT, ama: "C ++ böyle bir kuralı [değerlendirmek için n sabit bir ifade olarak] ". Sadece, bazen, bu ifadeyi gerçekten doğru yapmak için, yerine koymanız gerekir constexpr. Sadece kullanma const Bazı durumlarda işe yarayabilir, ancak bağlamına bağlı olarak, C ++ "sabit ifade" garanti etmez. Örneğin.: stackoverflow.com/questions/18996258/... - underscore_d
@artm: Haklısınız, C: tamsayı, yüzer, sayım ve karakterde 4 çeşit sabit vardır. - Keith Thompson
@underscore_d: Evet, C ++ kuralı biraz daha karmaşık - ancak bu özel durumda geçerli. Biraz çakal kelime ekledim. - Keith Thompson


Niye ya int x[n] nerede yanlış n bir const değeri?

n sabit değildir. const sadece söz veriyorum n Program yürütme sırasında değiştirilmemesi gereken 'salt okunur' bir değişkendir.
İçinde şunu unutmayın aksine , const Nitelikli değişkenler sabit değildir. Bu nedenle, bildirilen dizi değişken uzunluklu bir dizidir.
Değişken uzunluk dizilerini başlatmak için başlatıcı listesini kullanamazsınız.

C11-§6.7.9 / 3:

İlklendirilecek varlığın türü, bilinmeyen bir dizi veya tam bir nesne tipi olmalıdır. değişken uzunlukta dizi tipi değil.

Kullanabilirsiniz #define veya enum yapmak n bir sabit

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

21
2018-02-02 19:20



@Yahia Farghaly n bir değişkendir constama sabit değil. const C dilinde salt okunur anlamına gelir. - chux
@chux: Aslında, salt okunur olması garanti edilemez. Bu programcı tarafından derleyiciye bir garantidir. Derleyici, tüm ihlalleri algılayamayacak ve gereken çalışma zamanı ortamı tarafından belirlenemeyecektir. - too honest for this site
@Oalf - Doğru, OP için yanlış yönlendirilmiş aşırı basitleştirme yapıldı. - chux
not: C ++’da constNitelikli değişkenler, sabit ifadeler olabilir veya olmayabilir. const int n = rand() % 5; int x[n]; C cinsinden doğru ama C ++ değil! - M.M
@artm; Kullanabilirsiniz #define veya enum. - haccks


Bir diziyi tam olarak başlatıyorsanız, derleyicinin dizi boyutunu çıkarmasına izin vermek daha kolay, daha güvenli ve daha kalıcıdır:

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

Daha sonra dizi boyutunu değiştirmek için, boyutu değiştirmekten ziyade, yalnızca başlangıç ​​değerlerini değiştirmeniz gerekir. ve eşleştirilecek liste. Özellikle çok sayıda başlangıç ​​olduğunda faydalıdır.


7
2018-02-02 20:15





Buna rağmen n bir constBir VLA oluşturmak istemediğiniz sürece bir dizinin boyutunu tanımlamak için kullanamazsınız. Ancak, bir VLA'yı başlatmak için bir başlatıcı listesi kullanamazsınız.

Sabit boyutlu bir dizi oluşturmak için bir makro kullanın.

#define ARRAY_SIZE 5

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

3
2018-02-02 19:23



@chux: Statik VLA'nız olamaz. - too honest for this site
Bir blok veya işlev kapsamı içinde sabit tutmak istiyorsanız, sayılmış bir sabit de yapardı: enum { n = 5 }; int x[n] = { 1,1,3,4,6 }; - Ian Abbott
Hmm, bu ciddi bir tavsiye olamaz; Biri, sadece sabit bir boyut dizisi oluşturmak için potansiyel ve çok zor hataları bulmak için sembollerin küresel alanını kirletmez. - Sebastian Mach
Ugh. Adı değiştirmek için rahatsız etmeyin bu korkunç tavsiyeyi yapar. Herkes, Lütfen Hiç böyle bir makronun adını vermeyin. Sadece herhangi bir ortak adı, özellikle tek bir harfi ele geçirme sonucu ortaya çıkabilecek dehşeti düşünün. özellikle son derece genel n. Makrolar (veya en az% 99.9'u) olmalıdır HUGE_SHOUTY_AND_UGLY_NAMES, tam (ab) kullanımlarını zorlaştırır ve zorlaştırır. - underscore_d
@ underscore_d kullanımı n sadece örnekleme amaçlıydı ama iyi hazırlanmış. - R Sahu


Kodunuz semantik olarak farklı mı myfunc() İşte:

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 Gerçekten tüm bu sabit? Derleyicinin ne kadar alan ayırması gerektiğini düşünüyorsunuz? x[] (derleyici yapması gereken iş olduğu için)?

Diğerleri işaret ettiği gibi, cv-niteleyici const yapar değil "derleme sırasında ve her zaman için sabit olan bir değer" anlamına gelir. "Yerel kodun değişmemesi gereken bir değer" anlamına gelir.


2
2018-02-03 13:43