Dlaczego sizeof (x++) nie zwiększa x?
Oto kod skompilowany w dev C++ windows:
#include <stdio.h>
int main() {
int x = 5;
printf("%d and ", sizeof(x++)); // note 1
printf("%d\n", x); // note 2
return 0;
}
Oczekuję, że x
będzie 6 po wykonaniuUwaga 1 . Jednak wyjście to:
4 and 5
Czy ktoś może wyjaśnić dlaczego x
nie zwiększa się po Uwaga 1 ?
8 answers
Z C99 Standard (nacisk jest mój)
6.5.3.4/2
Operator sizeof otrzymuje rozmiar (w bajtach) swojego operandu, który może być wyrażeniem lub nazwą typu w nawiasie. Wielkość zależy od typu operandu. Wynikiem jest liczba całkowita. Jeśli Typ operandu jest typem tablicy o zmiennej długości, operand jest oceniany; w przeciwnym razie operand nie jest oceniany, a wynikiem jest liczba całkowita stała.
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-11-24 09:05:51
sizeof
jest Operator czasu kompilacji, Tak więc w czasie kompilacji sizeof
i jej operand zostają zastąpione przez wartość wyniku. Parametr nie jest oceniany (z wyjątkiem sytuacji, gdy jest to tablica o zmiennej długości); liczy się tylko Typ wyniku.
short func(short x) { // this function never gets called !!
printf("%d", x); // this print never happens
return x;
}
int main() {
printf("%d", sizeof(func(3))); // all that matters to sizeof is the
// return type of the function.
return 0;
}
Wyjście:
2
Jako short
zajmuje 2 bajty na mojej maszynie.
Zmiana typu zwracanej funkcji na double
:
double func(short x) {
// rest all same
Da 8
jako wyjście.
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-11-23 10:50:00
sizeof(foo)
bardzo stara się odkryć rozmiar wyrażenia w czasie kompilacji:
6.5.3.4:
Operator sizeof otrzymuje rozmiar (w bajtach) swojego operandu, który może być wyrażenie lub nazwa typu w nawiasie. Wielkość zależy od rodzaju operand. Wynikiem jest liczba całkowita. Jeżeli typem operandu jest tablica o zmiennej długości Typ, operand jest oceniany; w przeciwnym razie operand nie jest oceniany, a wynikiem jest liczba całkowita stała.
W skrócie: tablice o zmiennej długości, uruchamiane w czasie wykonywania. (Uwaga: tablice o zmiennej długości są specyficzną cechą -- a nie tablicami przypisanymi do malloc(3)
.) W przeciwnym razie obliczany jest tylko Typ wyrażenia i to w czasie kompilacji.
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-11-22 11:13:53
sizeof
jest operatorem wbudowanym w czas kompilacji i jest , a nie funkcją. Staje się to bardzo jasne w przypadkach, w których można go użyć bez nawiasu:
(sizeof x) //this also works
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-11-23 12:22:59
Uwaga
Ta odpowiedź została połączona z duplikatem, co wyjaśnia późną datę.
Oryginalny
Z wyjątkiem tablic o zmiennej długości sizeof Nie ocenia swoich argumentów. Możemy to zobaczyć w sekcji Projekt C99 standard 6.5.3.4
Operator sizeof paragraf 2 który mówi:
Operator sizeof otrzymuje rozmiar (w bajtach) swojego operandu, który może być wyrażenie lub nazwa typu w nawiasie. Wielkość zależy od rodzaju operand. Wynikiem jest liczba całkowita. jeśli Typ operandu jest tablicą o zmiennej długości Typ, operand jest oceniany; w przeciwnym razie operand nie jest oceniany, a wynikiem jest stała całkowita.
A comment (now removed ) asked if something like this would evaluate at run-time:
sizeof( char[x++] ) ;
I rzeczywiście, coś takiego też by zadziałało (Zobacz też oboje żyją):
sizeof( char[func()] ) ;
Ponieważ obie są tablicami o zmiennej długości. Chociaż, nie widzę wiele praktycznego zastosowania w żadnym z nich.
Uwaga, tablice o zmiennej długości są objęte sekcją draft C99 standard 6.7.5.2
Tabela 4:
[...] Jeżeli rozmiar jest wyrażeniem o stałej całkowitej, A Typ elementu ma znaną stałą wielkość, to typ tablicy nie jest typem tablicy o zmiennej długości; w przeciwnym razie typ tablicy jest typem tablicy o zmiennej długości.
Update
W C11 odpowiedź zmienia się dla przypadku VLA, w niektórych przypadkach nie jest określone, czy wyrażenie size Jest oceniane, czy nie. Z sekcji 6.7.6.2
array declarators {[20] } which says:
[...] Gdzie wyrażenie size Jest częścią operandu sizeof operator i zmiana wartości wyrażenia size Nie wpływ na wynik operatora, nie jest określone, czy obliczane jest wyrażenie rozmiaru.
Na przykład w takim przypadku (zobacz to na żywo):
sizeof( int (*)[x++] )
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-10-17 01:08:03
Ponieważ operand sizeof
operatora nie jest oceniany, możesz to zrobić:
int f(); //no definition, which means we cannot call it
int main(void) {
printf("%d", sizeof(f()) ); //no linker error
return 0;
}
Demo Online: http://ideone.com/S8e2Y
Oznacza to, że nie musisz definiować funkcji f
, jeśli jest ona używana tylko w sizeof
. Technika ta jest najczęściej używana w metaprogramowaniu szablonów C++, ponieważ nawet w C++ operand sizeof
nie jest oceniany.
Dlaczego to działa? Działa, ponieważ operator sizeof
nie działa na wartość , zamiast tego działa na typ wyrażenia. Więc kiedy piszesz sizeof(f())
, działa on na typie wyrażenia f()
, a który jest niczym innym jak typem zwracanym funkcji f
. Typ zwracania jest zawsze taki sam, bez względu na to, jaką wartość zwracałaby funkcja, gdyby faktycznie wykonywała.
W C++ możesz nawet to:
struct A
{
A(); //no definition, which means we cannot create instance!
int f(); //no definition, which means we cannot call it
};
int main() {
std::cout << sizeof(A().f())<< std::endl;
return 0;
}
Jednak wygląda na to, że w sizeof
najpierw tworzę instancję A
, pisząc A()
, a następnie wywołując funkcję {[3] } Na instancji, przez pisanie A().f()
, ale nic takiego się nie dzieje.
Demo: http://ideone.com/egPMi
Oto kolejny temat, który wyjaśnia kilka innych ciekawych właściwości sizeof
:
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
2017-05-23 12:26:33
Wykonanie nie może nastąpić podczas kompilacji. Więc ++i
/i++
nie ma mowy. Również sizeof(foo())
nie wykona funkcji, ale zwróci prawidłowy typ.
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-11-27 15:33:49
sizeof()
operator podaje tylko rozmiar typu danych, nie ocenia elementów wewnętrznych.
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-28 01:36:38