sizeof biorąc dwa argumenty

W C. 1. 3 C++ IS (2003. Jest w C++11 jest, too), standard wskazuje na różnicę między ISO C i C++; mianowicie, dla

char arr[100];

sizeof(0, arr) zwraca sizeof(char*) W C, ale 100 w C++.

Nie mogę znaleźć dokumentacji sizeof biorąc dwa argumenty. Oczywistym zaletą jest operator przecinka, ale nie sądzę: sizeof(arr) W C jest 100; sizeof(0, arr) is sizeof(char*). Zarówno sizeof(0, arr) jak i sizeof(arr)100 W C++.

Mogę pominąć cały sens IS w tym kontekście. Can ktoś pomoże? Jest to podobne do pytania omawianego w 2009 roku, ale nikt nie odniósł się do IS i nie sądzę, aby została udzielona prawidłowa odpowiedź.


Edit: właściwie, IS mówi o operatorze przecinka. Z jakiegoś powodu (0, arr) zwraca char* W C, ale char[100] W C++. Dlaczego?

Author: Nawaz, 2011-06-13

7 answers

W C Tablica rozkłada się do wskaźnika, ze względu na inną specyfikację operatora przecinka w odniesieniu do wartości R i lvalues (nie jedyne miejsce, gdzie można znaleźć taką różnicę). W C++ Tablica pozostaje tablicą, dając prawidłowy wynik.

 23
Author: Puppy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-13 14:16:01

W C operator przecinka nie wytwarza lvalue, w konsekwencji tablica arr, która jest lvalue rozpada się na typ wskaźnika, który jest rvalue (w tym przypadku). Tak więc sizeof(0,arr) staje się równoważne sizeof(char*), ze względu na konwersję lvalue-to-rvalue.

Ale w C++ operator przecinka tworzy lvalue. Nie ma konwersji lvalue-to-rvalue . Więc sizeof(0,arr) pozostaje taka sama, co jest równoważne sizeof(char[100]).

Przy okazji, sizeof nie jest funkcją, jest operatorem. Tak więc poniższe jest całkowicie poprawne C++ (i C, jeśli sobie wyobrazić printf zamiast cout):

int a[100], b[200], c[300], d[400];
cout << sizeof(a,b,c,d) << endl;

Demo: http://www.ideone.com/CtEhn

Możesz pomyśleć, że przekazałem 4 operandy do sizeof, ale to jest złe. sizeof operuje na wyniku operatorów przecinków. I to z powodu wielu operatorów przecinków widzisz wiele operandów.

4 operandy z 3 operatorami przecinkowymi; podobnie jak w 1+2+3+4, są 3 operatory, 4 operandy.

The powyższe jest równoważne następującym (poprawnym w C++0x):

auto & result = (a,b,c,d); //first all comma operators operate on the operands.
cout << sizeof (result) << endl; //sizeof operates on the result

Demo: http://www.ideone.com/07VNf

Więc to przecinek operator sprawia, że czujesz, że istnieje wiele argumentów. Tutaj comma jest operatorem, ale w wywołaniu funkcji comma nie jest operatorem, jego zwykłym separatorem argumentów.

function(a,b,c,d); //here comma acts a separator, not operator.

Więc sizeof(a,b,c,d) Działa na typie wyniku , operatorów, dokładnie w tym samym sposób, sizeof(1+2+3+4) działa na typie wyniku operatorów +.

Zauważ również, że nie możesz napisać sizeof(int, char, short), właśnie dlatego, że przecinek operator nie może operować na typach . Działa tylko na wartość. Myślę, że {[8] } jest jedynym operatorem w C i C++, który może działać również na typach . W C++ istnieje jeszcze jeden operator, który może operować na typach . Jego nazwa to typeid.

 46
Author: Nawaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-12 08:26:25

Jest operatorem przecinkowym. A różnica, o której mówisz, nie ma absolutnie nic wspólnego z sizeof. Różnica jest tak naprawdę w lvalue-to-rvalue, array-to-pointer i podobnych zachowaniach rozpadu między językami C i C++.

Język C jest pod tym względem dość korzystny: tablice rozpadają się na wskaźniki praktycznie natychmiast (z wyjątkiem bardzo niewielu specyficznych kontekstów), dlatego wynik wyrażenia 0, arr mA typ char *. Jest odpowiednikiem 0, (char *) arr.

W języku C++ tablice zachowują "tablice" znacznie dłużej. W przypadku użycia w kontekście , tablice operatorów nie rozpadają się na wskaźniki (a wartości LV nie rozpadają się na wartości R), dlatego w C++ typ wyrażenia 0, arr jest nadal char[100].

To wyjaśnia różnicę w zachowaniu sizeof w tym przykładzie. ?: operator jest kolejnym przykładem operatora, który demonstruje podobną różnicę w zachowaniu rozkładu, tzn. sizeof(0 ? arr : arr) Da różne wyniki w C i C++. Zasadniczo wynika to z faktu, że operatory C zwykle nie zachowują wartości swoich operandów. Do zademonstrowania takiego zachowania można użyć wielu operatorów.

 6
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-13 17:23:59

To nie jest sizeof przyjmowanie dwóch argumentów. sizeof jest operatorem, a nie funkcją.

Weź pod uwagę, że (0, arr) jest wyrażeniem używającym operatora przecinka, a Wszystko inne wypada na swoje miejsce.

 5
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-13 14:18:32

sizeof nie wymaga dwóch argumentów. Ale to też nie jest funkcja, więc (...) nie rozgraniczają argumentów funkcji, są tylko opcjonalna część składni i wymuszenie grupowania. Kiedy piszesz sizeof(0, arr), argument do sizeof jest pojedynczym wyrażeniem 0, arr. Pojedyncze wyrażenie z operatorem przecinka, które ocenia wyrażenie na lewo od przecinka, wyrzuca jego wartość (ale nie jego skutki uboczne), następnie oblicza wyrażenie na prawo od przecinka, i wykorzystuje swoją wartość jako wartość pełnego wyrażenia.

Nie jestem pewien co do C, ale to może być różnica między langauges. W C++ konwersja tablicy na wskaźnik nie zachodzi, chyba że jest potrzebne; w C, O ile dobrze pamiętam, standard mówi, że to zawsze odbywa się z wyjątkiem pewnych kontekstów. W tym jako operator sizeof. W tym przypadku, ponieważ operator przecinka nie mieć ograniczenia w odniesieniu do rodzajów jego operandów, konwersja tablicy na wskaźnik nie ma miejsca w C++. W C, an operatand operatora przecinka nie jest wymieniony w wyjątkach, więc konwersja tablicy na wskaźnik ma miejsce. (W tym przypadku tablica jest operandem operatora przecinka, a nie sizeof.)

 3
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-13 14:44:58

Najlepszym sposobem, aby zobaczyć, co może się tutaj dziać, jest spojrzenie na gramatykę w standardzie. Jeśli spojrzymy na wersję standardową C99 6.5.3 operatory jednoargumentowe paragraf 1 możemy zauważyć, że gramatyka dla sizeof to:

sizeof unary-expression
sizeof ( type-name )

Więc drugi nie ma zastosowania, ale jak ma zastosowanie sizeof unary-expression w tym przypadku? Jeśli spojrzymy na sekcję A.2.1 wyrażenia ze standardu szkicu i działają przez gramatykę w ten sposób:

unary-expression -> postfix-expression -> primary-expression -> ( expression )

Otrzymujemy nawiasy wokół wyrażenie i teraz wystarczy spojrzeć na gramatykę operator przecinka z sekcji 6.5.17 operator Przecinka i widzimy:

expression:
  assignment-expression
  expression , assignment-expression

Więc mamy teraz:

sizeof( expression , assignment-expression )
                   ^
                   |
                   comma operator

Zarówno wyrażenie jak i assignment-expression mogą doprowadzić nas do primary-expression , które ma następującą gramatykę:

primary-expression:
  identifier
  constant
  string-literal
  ( expression )

And 0 is a constant and arr is a identifier so we mieć:

 sizeof( constant , identifier )

Więc co robi operator przecinka tutaj? Sekcja 6.5.17 akapit 2 says:

Lewy operand operatora przecinka jest oceniany jako wyrażenie void; jest punkt sekwencji po jego ocenie. Następnie jest obliczany właściwy operand; wynik ma swój typ i wartość.97)

Ponieważ operator przecinka nie jest jednym z WYJĄTKÓW, gdzie tablica nie jest konwertowana na wskaźnik, daje pointer (jest to opisane w sekcji 6.3.2.1 Lvalues, arrays, and function designators ), co oznacza, że kończymy na:

sizeof( char * )

W C++ gramatyka jest dość podobna, więc kończymy w tym samym miejscu, ale operatory przecinków działają inaczej. Sekcja C++ draft standard5.18 operator Przecinka mówi:

[...] Typ i wartość wyniku są typem i wartością prawego operandu; wynik należy do tej samej kategorii wartości, co jej prawy operand[...]

Więc i array-to-pointer konwersja nie jest wymagana i tak kończymy na:

sizeof( char[100] ) 
 2
Author: Shafik Yaghmour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-26 04:45:27

Jak już kilka osób powiedziało, i chcę dodać tylko jedną rzecz, sizeof jest operatorem przyjmującym wyrażenie lub wyrażenie cast. Z tego powodu wziąłem zwyczaj pisania parantezy do wielkości tylko, jeśli jest wyrażeniem odlewanym.

 char *arr;
 struct xxx { ... } v;

Napiszę

sizeof arr 
sizeof v

Ale

sizeof (struct xxx)       /* Note the space after the sizeof, it's important */
sizeof (char *)

Robię to samo z return bez nawiasu, ponieważ nie jest to wywołanie funkcji, a jeśli umieszczę nawias, to dlatego, że poniższe wyrażenie ich potrzebuje.

 1
Author: Patrick Schlüter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-27 10:18:26