Hem C hem de C ++ 'da geçerli olan kod, her dilde derlendiğinde farklı davranışlar üretebilir mi?


664

C ve C ++ 'nın birçok farkı vardır ve geçerli C kodlarının tümü geçerli C ++ kodu değildir.
("Geçerli" ile tanımlanmış davranışa sahip standart kodu kastediyorum, yani uygulamaya özgü / tanımsız / vb. Değil)

C ve C ++ 'da geçerli bir kod parçasının, her dilde standart bir derleyici ile derlendiğinde farklı davranışlar üretebileceği herhangi bir senaryo var mı ?

Makul / yararlı bir karşılaştırma yapmak için (pratikte yararlı bir şey öğrenmeye çalışıyorum, soruda belirgin boşluklar bulmaya çalışmıyorum), varsayalım:

  • Önişlemci ile ilgili hiçbir şey yok (bu, hiçbir hack #ifdef __cplusplus, pragmas vb.
  • Uygulama tanımlı her şey her iki dilde de aynıdır (örn. Sayısal sınırlar, vb.)
  • Her standardın makul sürümlerini karşılaştırıyoruz (örneğin, C ++ 98 ve C90 veya üstü)
    Sürümler önemliyse, lütfen her birinin hangi sürümlerinin farklı davranışlar ürettiğini belirtin.

11
Bu arada, aynı anda C ve C ++ olan bir lehçede programlamak yararlı olabilir. Bunu geçmişte ve şu anki bir projede yaptım: TXR dili. İlginç bir şekilde, Lua dilinin geliştiricileri de aynı şeyi yaptılar ve bu lehçeye "Temiz C" diyorlar. C ++ derleyicilerinden daha iyi derleme zamanı denetimi ve muhtemelen ek yararlı tanılama avantajından faydalanırsınız, ancak C taşınabilirliğini korursunuz.
Kaz

9
Bu soruyu daha fazla görüşe sahip olduğumdan ve yanıtları iptal ettiğinden, eski soruyu bu soruya birleştirdim. Bu hala yapıcı olmayan bir soruya bir örnektir, ancak evet, çünkü SO kullanıcılarına bir şeyler öğretiyor. Sadece yapışmadan önce sorunun durumunu yansıtmak için yapıcı değil olarak kapatıyorum. Katılıp tekrar açabilirsiniz.
George Stocker

13
Ben bir "evet" ve ardından bir örnek (aşağıda kanıtlandığı gibi) ile objektif olarak cevaplanabilir düşünüyorum düşünüyorum gibi yeniden oylama. İnsanların kendilerinden ilgili davranışları öğrenebilmeleri yapıcı olduğunu düşünüyorum.
Anders Abel

6
@AndersAbel Hepsi doğru olan saf cevap sayısı, açıkça bir liste haline getirme sorusu olarak kaldığını gösteriyor. Liste almadan bu soruyu sormanın hiçbir yolu yoktu.
dmckee --- eski moderatör kedi yavrusu

2
@dmckee Değeri için sana katılıyorum. Ancak, C ++ etiketi insanlar ... Diyelim ki ... alıngan .
George Stocker

Yanıtlar:


397

C ve C ++ için geçerli olan aşağıdakiler (büyük olasılıkla) iC ve C ++ 'da farklı değerlerle sonuçlanır :

int i = sizeof('a');

Farkın açıklaması için C / C ++ 'daki karakter boyutu (' a ') konusuna bakın .

Dan Bir diğeri bu makalede :

#include <stdio.h>

int  sz = 80;

int main(void)
{
    struct sz { char c; };

    int val = sizeof(sz);      // sizeof(int) in C,
                               // sizeof(struct sz) in C++
    printf("%d\n", val);
    return 0;
}

8
Kesinlikle bu beklemiyordum! Biraz daha dramatik bir şey umuyordum ama bu hala faydalı, teşekkürler. :) +1
user541686

17
İkinci örnek +1, C ++ 'nın structyapı adlarından önce gerektirmediği için iyi bir örnektir .
Seth Carnegie

1
@Andrey Bir süre önce aynı şeyi düşündüm ve test ettim ve beklentilerimin aksine stc olmadan GCC 4.7.1 üzerinde çalıştı. Bu GCC'de bir hata mı?
Seth Carnegie

3
@SethCarnegie: Uygun olmayan bir programın çalışmasına gerek yoktur, ancak çalışacağı da garanti edilmez.
Andrey Vihrov

3
struct sz { int i[2];};C ve C ++ anlamına gelir sahip farklı değerler üretmek. (Sizeof (int) == 1 olan bir DSP Oysa olabilir aynı değeri üretir).
Martin Bonner, Monica

464

C ve C ++ 'da işlev çağrıları ve nesne bildirimleri arasındaki farkın yanı sıra C90'ın bildirilmemiş işlevlerin çağrılmasına izin verdiği gerçeğinden yararlanan bir örnek:

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

int f() {
    return printf("hello");
}

C ++ 'da geçici bir fşey yaratıldığından ve yok edildiğinden hiçbir şey yazdırmaz , ancak C90'da helloişlevler bildirilmeden çağrılabildiğinden yazdırılır .

Adın fiki kez kullanıldığını merak ediyorsanız , C ve C ++ standartları buna açıkça izin verir ve bir nesne yapmak struct fistiyorsanız, yapıyı istiyorsanız belirsizleştirmek veya structişlevi istiyorsanız bırakın .


7
Kesinlikle C altında konuşmak, bu derlenmeyecektir, çünkü "int f ()" bildirimi "int main ()"
tanımından sonradır

15
@Sogartar, gerçekten mi? codepad.org/STSQlUhh C99 derleyicileri size bir uyarı verir, ancak yine de derlemenize izin verir.
jrajav

22
@ C fonksiyonlarındaki Sogartar'ın dolaylı olarak bildirilmesine izin verilir.
Alex B

11
@AlexB C99 ve C11'de değil.

6
@jrajav Bunlar C99 derleyicisi değil. Bir C99 derleyicisi, bildirilmemiş tanımlayıcıları bir sözdizimi hatası olarak algılar. Bunu yapmayan bir derleyici ya bir C89 derleyicisi ya da bir ön-standart ya da başka tür bir uyumsuz derleyicidir.

430

C ++ ile C90 arasında, uygulama tanımlı olmayan farklı davranışlar elde etmenin en az bir yolu vardır. C90'ın tek satır yorumları yok. Biraz dikkatle, bunu C90 ve C ++ 'da tamamen farklı sonuçlara sahip bir ifade oluşturmak için kullanabiliriz.

int a = 10 //* comment */ 2 
        + 3;

C ++ 'da //, satırın sonuna kadar her şey bir yorumdur, bu yüzden bu şu şekilde çalışır:

int a = 10 + 3;

C90'ın tek satır yorumları olmadığından, yalnızca /* comment */bir yorumdur. İlk /ve 2her ikisi de başlatmanın parçalarıdır, bu yüzden ortaya çıkar:

int a = 10 / 2 + 3;

Yani, doğru bir C ++ derleyici 13, ama kesinlikle doğru bir C90 derleyici 8 verecektir. Tabii ki, ben burada rastgele sayılar seçtim - uygun gördüğünüz gibi diğer numaraları kullanabilirsiniz.


34
WHOA bu akıllara durgunluk veren !! Asla düşünmeyeceğim tüm olası şeylerin yorumları davranışları değiştirmek için kullanılabilir haha. +1
user541686

89
olmadan bile , geçerli (unary +) 2olarak okunur 10 / + 3.
Benoit

12
Şimdi eğlenmek için, C ve C ++ her ikisinin de farklı aritmetik ifadeleri aynı sonuca göre değerlendirmesini sağlayacak şekilde değiştirin.
Ryan

21
@RyanThompson Önemsiz. s / 2/1 /
2/1

4
@Mehrdad Yanlış mı yoksa yorumlar önişlemci ile mi ilgili? Bu nedenle, sorunuzdan olası bir cevap olarak hariç tutulmalıdırlar! ;-)
Ale

179

C90 ve C ++ 11 ( intvs. double):

#include <stdio.h>

int main()
{
  auto j = 1.5;
  printf("%d", (int)sizeof(j));
  return 0;
}

C cinsinden auto yerel değişken anlamına gelir. C90'da değişken veya işlev türünü atlamak uygundur. Varsayılan olarak int. C ++ 11'de autotamamen farklı bir şey ifade eder, derleyiciye değişken türünü başlatmak için kullanılan değerden çıkarmasını söyler.


10
C90 var automı?
Seth Carnegie

22
@SethCarnegie: Evet, bu bir depolama sınıfı; bunu atladığınızda varsayılan olarak olan şeydir, bu yüzden kimse onu kullanmamıştır ve anlamını değiştirmiştir. Bence bu intvarsayılan olarak. Bu akıllıca! +1
user541686

5
C11'in üstü kapalı- yoktur int.
R .. GitHub BUZA YARDIMCI DURDUR

23
@ KeithThompson Ah, sanırım çıkarım demek istedin int. Yine de, tonlarca eski kodun bulunduğu ve pazar liderinin hala C99'u uygulamadığı ve bunu yapmak gibi bir amacı olmayan gerçek dünyada, "C'nin eski bir versiyonunun" konuşması saçmadır.
Jim Balter

11
"Her değişkenin açık bir depolama sınıfı olmalıdır ZORUNLU.
btown

120

Daha önce bahsetmediğim başka bir örnek, bu bir önişlemci farkını vurgulamaktadır:

#include <stdio.h>
int main()
{
#if true
    printf("true!\n");
#else
    printf("false!\n");
#endif
    return 0;
}

Bu, C'de "false" ve C ++ 'da "true" yazdırır. C'de, tanımsız herhangi bir makro 0 olarak değerlendirilir. C ++' da 1 istisna vardır: "true" 1 olarak değerlendirilir.


2
İlginç. Bu değişimin ardındaki mantığı bilen var mı?
antred

3
çünkü "true" anahtar bir kelime / geçerli değerdir, bu nedenle herhangi bir "true value" gibi (true değeri gibi) true olarak değerlendirilir. C # 'da da "false" yazdırmak için #define true false yapabilirsiniz;)
CoffeDeveloper

22
#define true false Bo_ಠ
Bryan Boettcher

2
@DarioOO böyle bir yeniden tanımlama UB ile sonuçlanmaz mı?
Ruslan

3
@DarioOO: Evet, yanılıyorsunuz. Anahtar kelimelerin yeniden tanımlanmasına izin verilmez, cezanın kadere bırakılması (UB). Önişlemci, ayrı olmayan bir derleme aşamasıdır.
Deduplicator

108

C ++ 11 standardına göre:

a. Virgül operatörü, C ++ 'da lvalue-rvalue dönüşümü gerçekleştirir, ancak C ++' da değil:

   char arr[100];
   int s = sizeof(0, arr);       // The comma operator is used.

C ++ 'da bu ifadenin değeri 100 ve C' de bu olacaktır sizeof(char*).

b. C ++ 'da numaralandırıcı türü numaralandırmasıdır. C'de sayıcı türü int.

   enum E { a, b, c };
   sizeof(a) == sizeof(int);     // In C
   sizeof(a) == sizeof(E);       // In C++

Bu, sizeof(int)eşit olmayabileceği anlamına gelir sizeof(E).

c. C ++ 'da boş params listesiyle bildirilen bir işlev argüman almaz. C'de boş parametreler listesi, işlev parametrelerinin sayısı ve türünün bilinmediği anlamına gelir.

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C

Birincisi, Alexey gibi uygulama tanımlı. Ama +1.
Seth Carnegie

1
@Seth, Yukarıdaki tüm malzemeler doğrudan C ++ 11 standardının Ek C.1'inden alınmıştır.
Kirill Kobelev

Evet ama yine de uygulama tanımlı. sizeof(char*)100 olabilir, bu durumda ilk örnek C ve C ++ 'da aynı gözlemlenebilir davranışı üretecektir (yani elde etme yöntemi sfarklı olsa da , ssonuç 100 olur). OP, bu tür bir uygulama tanımlı davranışın sadece dil-avukat cevaplarından kaçınmak istediğinden iyi olduğunu belirtti, bu yüzden birincisi istisnasıyla iyi. Ama ikincisi her durumda iyidir.
Seth Carnegie

5
Kolay bir düzeltme var - örneği şu şekilde değiştirin:char arr[sizeof(char*)+1]; int s = sizeof(0, arr);
Mankarse

5
Uygulama tanımlı farklılıklardan kaçınmak için de kullanabilirsiniz void *arr[100]. Bu durumda, bir öğe aynı öğeye işaretçi ile aynı boyuttadır, bu nedenle 2 veya daha fazla öğe olduğu sürece, dizi ilk öğesinin adresinden daha büyük olmalıdır.
finnw

53

Bu program 1C ++ ve C olarak yazdırılır 0:

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

int main(void)
{
    int d = (int)(abs(0.6) + 0.5);
    printf("%d", d);
    return 0;
}

Olduğundan bu olur double abs(double), C ++ aşırı yük böylece abs(0.6)getiri 0.6C döndürür iken 0, çünkü çağırmadan önce örtük çift to-int dönüşüm int abs(int). C fabsile çalışmak için kullanmanız gerekir double.


5
başka birisinin kodunda hata ayıklamak zorunda kaldı. Bunu nasıl sevdim. Her neyse, programınız C ++ 'da 0 yazdırıyor. C ++ 0 returnin karşılaştırma ilk bkz başlığı "CMATH" kullanmak zorunda ideone.com/0tQB2G 1 dönen 2 one ideone.com/SLeANo
CoffeDeveloper

Hata ayıklama yoluyla bu farkı bulan tek kişi olmadığımı duyduğuma sevindim / üzgünüm. Sadece VS2013'te test edildi, yalnızca bu içeriğe sahip bir dosya boşluğu, uzantı .cpp ise 1, uzantı .c ise 0 çıktısı verir. Görünüşe göre <math.h> dolaylı olarak VS'ye dahil edilmiştir.
Pavel Chikulaev

VS C ++ 'da olduğu gibi, <math.h> küresel ad alanına C ++ şeyler içerir, burada GCC için olduğu gibi değildir. Ancak hangisinin standart davranış olduğundan emin değilim.
Pavel Chikulaev

2
Bu özel kod örneği uygulamaya bağlıdır: stdlib.hyalnızca tanımlar abs(int)ve abs(long); sürüm abs(double)tarafından bildirilir math.h. Yani bu program hala abs(int)sürümü çağırabilir . Ayrıca dahil edilmesine stdlib.hneden olup olmadığı bir uygulama detayıdır math.h. (Ben abs(double)arandı, ancak diğer aspecs math.hdahil değildi bir hata olacağını düşünüyorum ).
MM

1
İkincil bir sorun da, C ++ standardının <math.h>ek yükleri de içerdiğini söylese de; pratikte, form <cmath>kullanılmadıkça tüm büyük derleyicilerin bu aşırı yüklenmeleri içermediği anlaşılmaktadır .
MM

38
#include <stdio.h>

int main(void)
{
    printf("%d\n", (int)sizeof('a'));
    return 0;
}

C'de, bu sizeof(int), geçerli sistemdeki değeri ne olursa olsun yazdırır.4 günümüzde yaygın olarak kullanılan çoğu .

C ++ 'da, bu 1 yazmalıdır.


3
Evet, aslında bu numaraya aşinaydım, 'c' C'de bir int ve C ++ 'da bir karakter olmakla birlikte, burada listelenmesi hala iyi.
Sean

9
Bu ilginç bir röportaj sorusu yaratabilir - özellikle CV'lerine c / c ++ uzmanı koyan insanlar için
Martin Beckett

2
Yine de bir tür gizli. Sizeof'in tüm amacı, bir türün ne kadar büyük olduğunu tam olarak bilmenize gerek yoktur.
Dana the Sane

13
C'de değer uygulaması tanımlanmıştır ve 1 bir olasılıktır. (C ++ 'da belirtildiği gibi 1 yazdırması gerekir.)
Windows programcısı

3
Aslında her iki durumda da tanımlanmamış bir davranışa sahiptir. %diçin doğru biçim belirteci değil size_t.
R .. GitHub BUZA YARDIMCI DURDUR

37

Başka bir sizeoftuzak: boole ifadeleri.

#include <stdio.h>
int main() {
    printf("%d\n", (int)sizeof !0);
}

Bu sizeof(int)ifade C'ye eşittir , çünkü ifade tiptir int, ancak genellikle C ++ 'da 1'dir (olması gerekmese de). Pratikte neredeyse her zaman farklıdırlar.


6
Biri !için yeterli olmalı bool.
Alexey Frunze

4
!! boolean dönüşüm operatörü int olduğunu
EvilTeach

1
sizeof(0)tamsayı bir değer olduğu 4için hem C hem de C ++ ' 0dadır. sizeof(!0)bir 4C ve 1C ++. Mantıksal NOT bool tipi işlenenlerde çalışır. İnt değeri 0dolaylı olarak false(bir bool değeri) dönüştürülürse , ters çevrilir ve sonuçlanır true. Hem trueve falseC ++ bool SağDeğerler ve sizeof(bool)olduğunu 1. Ancak C olarak !0değerlendirilir 1, int türünde bir değerdir. C programlama dilinde varsayılan olarak bool veri türü yoktur.
Galaxy

26

C ++ Programlama Dili (3. Baskı) üç örnek verir:

  1. @Adam Rosenfield'ın belirttiği gibi sizeof ('a');

  2. // gizli kod oluşturmak için kullanılan yorumlar:

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
  3. Örneğin vb. Gibi yapıları vb.



21

C ++ Standardı tarafından listelenen bir diğeri:

#include <stdio.h>

int x[1];
int main(void) {
    struct x { int a[2]; };
    /* size of the array in C */
    /* size of the struct in C++ */
    printf("%d\n", (int)sizeof(x)); 
}

böylece dolgu farklılıkları olsun?
v.oddou

Ah üzgünüm anladım x, üstte başka bir tane var . "dizi a" dediğini sanıyordum .
v.oddou

20

C ++ 'daki satır içi işlevler, C ++' daki gibi olmayan dış kapsama varsayılan değerdir.

Aşağıdaki iki dosyayı birlikte derlemek, GNU C durumunda "I inline" yazıyor ancak C ++ için hiçbir şey yazdırmıyor.

Dosya 1

#include <stdio.h>

struct fun{};

int main()
{
    fun();  // In C, this calls the inline function from file 2 where as in C++
            // this would create a variable of struct fun
    return 0;
}

Dosya 2

#include <stdio.h>
inline void fun(void)
{
    printf("I am inline\n");
} 

Ayrıca, C ++ , varsayılan olan C'den farklı constolarak , herhangi bir genel nesneyi static, açıkça bildirilmediği sürece dolaylı olarak ele alır .externextern


Gerçekten öyle düşünmüyorum. Muhtemelen bu noktayı kaçırdınız. Sadece kodu geçerli c ++ yapmak için kullanılan struct st tanımı ile ilgili değildir. Buradaki nokta, c vs c ++ 'daki satır içi işlevlerin farklı davranışlarını vurgulamasıdır. Aynı şey extern için de geçerlidir. Bunların hiçbiri çözümlerin hiçbirinde tartışılmamaktadır.
fkl

2
Satır içi işlevlerin farklı davranışı nedir ve externburada gösterilmiştir?
Seth Carnegie

Oldukça açık bir şekilde yazılmıştır. Msgstr "c ++ 'da olduğu gibi, c (c)' de dış kapsama satır içi işlevler (kod bunu gösterir). Ayrıca C ++, extern'in varsayılan olduğu C'den farklı olarak, açıkça extern olarak bildirilmediği sürece, herhangi bir const global'i dosya kapsamı olarak dolaylı olarak ele alır. msgstr "bunun için örnek oluşturulabilir" #:. Şaşkınım - Anlaşılamaz mı?
fkl

12
@fayyazkl Gösterilen davranış sadece arama ( struct funvs fn) arasındaki farktan kaynaklanır ve işlevin satır içi olup olmadığıyla ilgisi yoktur. Niteleyiciyi kaldırırsanız sonuç aynıdır inline.
Alex B

3
ISO C'de bu program oluşmuştur: inlineC99'a kadar eklenmedi, ancak C99'da fun()kapsamdaki bir prototip olmadan çağrılamaz . Bu cevabın sadece GNU C için geçerli olduğunu varsayıyorum.
MM

16
struct abort
{
    int x;
};

int main()
{
    abort();
    return 0;
}

C ++ 'da 0 veya C' de 3 çıkış koduyla döner.

Bu hile muhtemelen daha ilginç bir şey yapmak için kullanılabilir, ancak C'ye lezzetli olacak bir yapıcı oluşturmanın iyi bir yolunu düşünemedim. Kopya yapıcısıyla benzer şekilde sıkıcı bir örnek yapmaya çalıştım, taşınabilir olmayan bir şekilde de olsa geçilebilir:

struct exit
{
    int x;
};

int main()
{
    struct exit code;
    code.x=1;

    exit(code);

    return 0;
}

VC ++ 2005, C ++ modunda derlemeyi reddetti, ancak "çıkış kodu" nasıl yeniden tanımlandı şikayet. (Aniden nasıl programlanacağını unutmadıkça, bu bir derleyici hatası olduğunu düşünüyorum.) C olsa derlendiğinde 1 işlem çıkış kodu ile çıkıldı.


Exit kullanan ikinci örneğiniz maalesef gcc veya g ++ 'da derlenmemiştir. Yine de iyi bir fikir.
Sean

1
exit(code)Görünüşe göre codetür değişkeninin geçerli bir beyanıdır exit. (Farklı ama benzer bir sorun olan "en sinir bozucu ayrıştırma" konusuna bakın).
user253751

16
#include <stdio.h>

struct A {
    double a[32];
};

int main() {
    struct B {
        struct A {
            short a, b;
        } a;
    };
    printf("%d\n", sizeof(struct A));
    return 0;
}

Bu program, bir C ++ derleyicisi kullanılarak derlendiğinde 128( 32 * sizeof(double)) yazdırır ve4 kullanılarak derlendiğinde bir C derleyicisi kullanılarak .

Bunun nedeni, C'nin kapsam çözünürlüğü kavramına sahip olmamasıdır. C'de diğer yapılarda bulunan yapılar dış yapı kapsamına alınır.


Bu ilginç! (Sanırım 32*sizeof(double)32 yerine demek istiyorsun :))
user1354557


7

C ve C ++ global ad alanları arasındaki farkı unutmayın. Bir foo.cpp dosyanız olduğunu varsayalım

#include <cstdio>

void foo(int r)
{
  printf("I am C++\n");
}

ve bir foo2.c

#include <stdio.h>

void foo(int r)
{
  printf("I am C\n");
}

Şimdi her ikisinin de benzediği bir main.c ve main.cpp dosyanız olduğunu varsayalım :

extern void foo(int);

int main(void)
{
  foo(1);
  return 0;
}

C ++ olarak derlendiğinde, C ++ global ad alanındaki sembolü kullanır; C'de C olanını kullanır:

$ diff main.cpp main.c
$ gcc -o test main.cpp foo.cpp foo2.c
$ ./test 
I am C++
$ gcc -o test main.c foo.cpp foo2.c
$ ./test 
I am C

Bağlantı özellikleri mi demek istiyorsun?
user541686

isim mangling. C ++ adlarının ön ekleri ve son ekleri varken C değil
CoffeDeveloper

Ad yönetimi C ++ belirtiminin bir parçası değildir. C dilinde yasaklanmış mı?
skyking

5
Bu tanımsız bir davranıştır (çoklu tanımı foo). Ayrı "genel ad alanları" yoktur.
MM

4
int main(void) {
    const int dim = 5; 
    int array[dim];
}

Bu, C ++ ve C99, C11 ve C17'de (C11, C17'de isteğe bağlı olmasına rağmen) geçerli olması bakımından oldukça tuhaftır; ancak C89'da geçerli değildir.

C99 + 'da, derleme zamanı türü yerine bir çalışma zamanı türüne sahip sizeof arrayolduğu ve C'de bir tamsayı sabit ifadesi olmadığı için normal diziler üzerinde kendine özgü özellikleri olan değişken uzunluklu bir dizi oluşturur . C ++' da tür tamamen statiktir.


Buraya bir başlatıcı eklemeye çalışırsanız:

int main(void) {
    const int dim = 5; 
    int array[dim] = {0};
}

değişken uzunluktaki dizilerin bir başlatıcısı bulunamadığından , geçerli C ++ ancak C değil.


0

Bu, C ve C ++ 'da değer ve değerlerle ilgilidir.

C programlama dilinde, hem artım öncesi hem de artım sonrası işleçleri, değerleri değil, değerleri döndürür. Bu, =atama operatörünün sol tarafında olamayacakları anlamına gelir . Bu ifadelerin her ikisi de C'de bir derleyici hatası verecektir:

int a = 5;
a++ = 2;  /* error: lvalue required as left operand of assignment */
++a = 2;  /* error: lvalue required as left operand of assignment */

C ++, ancak önceden arttırma operatör döner lvalue artırma sonrası operatör rvalue döndürür iken,. Bu, ön artış operatörü ile bir ifadenin =atama operatörünün sol tarafına yerleştirilebileceği anlamına gelir !

int a = 5;
a++ = 2;  // error: lvalue required as left operand of assignment
++a = 2;  // No error: a gets assigned to 2!

Şimdi neden böyle? Artırma sonrası değişken artırır ve olduğu gibi değişken döndürür önce artış oldu. Bu aslında sadece bir değerdir. A değişkeninin eski değeri geçici olarak bir kayıt defterine kopyalanır ve sonra a artırılır. Ancak a'nın eski değeri ifade tarafından döndürülür, bu bir değerdir. Artık değişkenin geçerli içeriğini temsil etmemektedir.

Önceden arttırma ilk artışlarla değişken ve oldu gibi o değişken döndürür sonra artış oldu. Bu durumda, değişkenin eski değerini geçici bir kayıt defterine depolamamız gerekmez. Değişkenin yeni değerini artırıldıktan sonra alırız. Böylece ön artış bir lvalue, değişken a'nın kendisini döndürür. Bu değeri başka bir şeye atamak için kullanabiliriz, aşağıdaki ifadeye benzer. Bu, değerin örtük bir değere dönüştürülmesidir.

int x = a;
int x = ++a;

Ön artış bir değer döndürdüğü için, buna bir şey de atayabiliriz. Aşağıdaki iki ifade aynıdır. İkinci ödevde, önce a artırılır, daha sonra yeni değerinin üzerine 2 yazılır.

int a;
a = 2;
++a = 2;  // Valid in C++.

3
Burada "C'de geçerli" yok.
o11c

0

Boş yapılar C boyutunda 0 ve C ++ 'da 1 boyuta sahiptir:

#include <stdio.h>

typedef struct {} Foo;

int main()
{
    printf("%zd\n", sizeof(Foo));
    return 0;
}

1
Hayır, fark, C'nin derleyici uzantısı dışında boş yapılara sahip olmamasıdır , yani bu kod eşleşmez "hem C hem de C ++ için geçerlidir"
Antti Haapala
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.