|
Виж темите без отговор | Виж активните теми
Дата и час: Пон Юли 27, 2026 3:23 pm
Интересно поведение на GCC
| Автор |
Съобщение |
|
slav4o.com
Ранг: Форумен бог
Регистриран на: Нед Яну 01, 2012 8:04 pm Мнения: 2663 Местоположение: София / Велико Търново
|
 Re: Интересно поведение на GCC
Направих тест sizeof("TEST") връща 5 sizeof("1234567890") връща 11
|
| Съб Ное 09, 2019 11:06 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30684 Местоположение: София
|
 Re: Интересно поведение на GCC
Ами ти с първите два кода декларираш пойнтер към литерал, а след това искаш sizeof на самият пойнтер. Във вторият си декларираш масив като си го определил че е с 12 елемента, и номрлано да ти връща 12. Ако беше char sizetest []="xxx" ще ти върне нещо различно.
|
| Съб Ное 09, 2019 11:32 pm |
|
 |
|
Jack
Ранг: Напреднал
Регистриран на: Вто Май 07, 2019 9:16 pm Мнения: 434 Местоположение: I bin thinkin’ this bin Gurindji country. We bin here longa time before them Vestey mob.
|
 Re: Интересно поведение на GCC
На семантикс аналайзера все му е тая за скобите, синтактик-анализа ще се обади само в случай че си сложил отваряща но не и затваряща. Ти си тоя който ще реве, ако не слушаш Керниган и парс-дървото ти се изгради в неправилния ред, т.е. - прецидънса на логическите и други оператори няма да се изпълнява в правилния ред и крайния резултат може да е странен и проблема с амбигуити-то на написното -трудно ловим.
|
| Нед Ное 10, 2019 12:08 am |
|
 |
|
palavrov
Ранг: Форумен бог
Регистриран на: Вто Окт 11, 2011 11:53 pm Мнения: 4582 Местоположение: Brussels / Пловдив
|
 Re: Интересно поведение на GCC
Предполагам, ме имаш в предвид {} скоби а не ()  Префиксните езици нямат скоби (Fort), постфиксните са само скоби (Lisp), инфиксните (C, Pascal, Java, ...) са по средата 
_________________ Мразя да мразя ...
|
| Нед Ное 10, 2019 12:40 pm |
|
 |
|
ec1832
Ранг: Минаващ
Регистриран на: Пон Ное 11, 2019 6:51 pm Мнения: 2
|
 Re: Интересно поведение на GCC
Спомням си някои особености в C, за низовите константи (string literals), масивите, и операторите амперсанд( &) и sizeof. В C, низови константи от вида "This is a string" се преобразуват в масиви, които са с такъв размер, колкото да съдържат символите в низа, плюс още един нулев байт за край на низа. Също така, в изразите в C, даннови обекти от тип 'масив от х' се преобразуват (неявно) в типове 'указател към х', с изключение на два случая. По този начин, в C, масивите и указателите са почти взаимозаменяеми, с изключение на два случая. А именно, в израз на C, когато даннов обект от тип 'масив от х', е операнд на оператор амперсанд( &) или sizeof, то той не се преобразува в тип 'указател към х', а си остава с тип 'масив от х'. Тези изключения имат някои особености. За съжаление, рядко вече имам възможност да пиша на C, написах за проба, да си припомня, следната програма, надявам се да е полезна за някого. Показват се някои от особеностите на операторите & и sizeof:  |  |  |  | Код: #include <stdio.h>
// Tested on a 32 bit machine, pointers are 32 bit (four bytes) in size
// In the C language, a data object of an 'array of x' type is implicitly converted in expressions to a // data object of type 'a pointer to x', with two exceptions: // when the data object of an 'array' type is an operand of the ampersand (&), or the 'sizeof' operator int main(void) {
// Expected: 12 - exceptional handling of arrays versus pointers. // An array is not converted to a pointer in the case of being an operand to an 'ampersand', // or a 'sizeof' operator (this case). // The type in this case remains an array: so there are 11 bytes in the string + 1 byte for the null terminator - 12 bytes in total printf("Line %i: %i, expected 12\n", __LINE__, sizeof "Test string"); // Expected: 12. Same as above, the dereference (*) and 'address-of' (ampersand, &) operators cancel each other printf("Line %i: %i, expected 12\n", __LINE__, sizeof * & "Test string"); // Expected 11: 12 byte for the character array, minus 1 printf("Line %i: %i, expected 11\n", __LINE__, sizeof "Test string" - 1); // Expected: 4. Pointer arithmetic - the size of a pointer to a 'char' (which is four bytes), minus 1 - yields a pointer, which is 4 bytes in size printf("Line %i: %i, expected 4\n", __LINE__, sizeof("Test string" - 1)); // Expected: 4. The size of a pointer (to whatever, in this case - an array), is 4 bytes in size printf("Line %i: %i, expected 4\n", __LINE__, sizeof & "Test string"); // Expected: 1. Dereference, the type pointed to by a 'pointer to char' is 'char', which is 1 byte in size printf("Line %i: %i, expected 1\n", __LINE__, sizeof * "Test string"); // Expected: 5. The size of a pointer, which is 4 bytes in size, plus one printf("Line %i: %i, expected 5\n", __LINE__, sizeof & "Test string" + 1); // Expected: 4. Address arithmetic - the result is the number of elements between the two pointers of the same type (pointers to 'char'), // which is of type 'size_t', which is 4 bytes in size on a 32 bit machine printf("Line %i: %i, expected 4\n", __LINE__, sizeof("Test string" - "another Test string"));
// Expected: 1. The size of an element of an 'array of char' type, which is a 'char' - 1 byte in size printf("Line %i: %i, expected 1\n", __LINE__, sizeof "Test string"[2]); // Expected: 4. The size of a pointer to an element of a 'char' array, which is a pointer to a 'char' - 4 bytes in size, as any other pointer on a 32 bit machine printf("Line %i: %i, expected 4\n", __LINE__, sizeof & "Test string"[2]);
// Expected: 12 - exceptional handling of arrays versus pointers. // The "test array" string literal is an operand to the ampersand(&) operator, so it is not // converted to type 'pointer to char' - instead, it remains of type 'array of 12 chars', so the // type of the expression '& "Test string"' is effectively a 'pointer to an array of 12 chars'. // Subscripting a 'pointer to an array of 12 chars' (in this case with index 2), yields // a data object of type 'array of 12 chars', which is 12 bytes in size printf("Line %i: %i, expected 12\n", __LINE__, sizeof (& "Test string")[2]); // Expected: 12 - exceptional handling of arrays versus pointers. // Same as above, the array subscript operator('[]') in C is commutative, // that is 'ptr[2]' is equivalent to '2[ptr]' printf("Line %i: %i, expected 12\n", __LINE__, sizeof 2[& "Test string"]); // Expected: 12 - exceptional handling of arrays versus pointers. // Same as above, but uses the pointer dereference('*') and address arithmetic, // instead of the array subscript('[]') operator printf("Line %i: %i, expected 12\n", __LINE__, sizeof * (2 + & "Test string"));
return 0; }
|  |  |  |  |
Ето така пробвам програмката, под mingw на Windows 10:  |  |  |  | Код: $ gcc sizeof-test.c
$ ./a.exe Line 15: 12, expected 12 Line 17: 12, expected 12 Line 19: 11, expected 11 Line 21: 4, expected 4 Line 23: 4, expected 4 Line 25: 1, expected 1 Line 27: 5, expected 5 Line 30: 4, expected 4 Line 33: 1, expected 1 Line 35: 4, expected 4 Line 43: 12, expected 12 Line 47: 12, expected 12 Line 51: 12, expected 12
|  |  |  |  |
|
| Пон Ное 11, 2019 8:51 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Интересно поведение на GCC
проблемът не е какво връща sizeof() а за какво се ползва. За дължина на стринг си има стандартна функция, за сравнение на стрингове също. Функциите за стрингове връщат същия резултат като функциите за памет, но само докато вместо ANSI не се наложи да се ползва някакъв друг енкодинг... В случая вероятно се разчита, че командите ще си останат винаги на английски, ама въпреки всичко по-добре да не се залагат бомбички, защото никога не се знае знае ли се 
|
| Пон Ное 11, 2019 9:23 pm |
|
 |
|
TheWizard
Ранг: Форумен бог
Регистриран на: Сря Апр 27, 2005 12:48 pm Мнения: 6094
|
 Re: Интересно поведение на GCC
 ам те не гледат какво съм "подчертал" - memcmp в горните постове компарваха стингове буква по буква нарочно сложих sizeof("тест")-1 да се види "показателно" кое броя
_________________ main[-1u]={1};
|
| Пон Ное 11, 2019 10:59 pm |
|
 |
|
slav4o.com
Ранг: Форумен бог
Регистриран на: Нед Яну 01, 2012 8:04 pm Мнения: 2663 Местоположение: София / Велико Търново
|
 Re: Интересно поведение на GCC
А аз предполагах че щом може char * comanda да стане = "TEST" , "ТEST" e char * или поне sizeof ще го разглежда като char * По-интересното при PIC-овете е, че TEST е низ от константни символи и го поставя във програмната памет, което пести от RAM паметта. на по-старите C компилатори виждам че има спецификатори rom и ram - примерно rom char chislo1. Някой ако знае подробности може да пише. Във XC8 гледам че ако се декларира като const данната става константа и отива във флаша. По-нтересното е как са събрани двете адресни пространства на данновата и програмната памети във едно, т.е. как е имплементирано в компилатора. Разбира се мен това не ме касае. Това което е важно и се вижда е, че низа заема брой символи + 3 = брой words в програмната флаш памет.
|
| Вто Ное 12, 2019 12:26 am |
|
 |
|
TheWizard
Ранг: Форумен бог
Регистриран на: Сря Апр 27, 2005 12:48 pm Мнения: 6094
|
 Re: Интересно поведение на GCC
sizeof() е препроцесор само - "брои" това което е поставено между скобите и "връща" константа в случая sizeof("тест") брои масив 4 букви + зеро char затваряш стринга
memcmp( command, "TEST", sizeof("1234")-1 ) в случая 1234 няма да присъства в кода, просто двата масива са равни по размер
за пиковете const не е "гаранция" че ще се "намират" във флаша - има една опция в настройката на проекта къде да идат константите... напрактика са някъде във флаша, но при startup може да ги преместиш в рама ... просто опция
_________________ main[-1u]={1};
|
| Вто Ное 12, 2019 12:54 am |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Интересно поведение на GCC
|
| Вто Ное 12, 2019 9:53 am |
|
 |
|
slav4o.com
Ранг: Форумен бог
Регистриран на: Нед Яну 01, 2012 8:04 pm Мнения: 2663 Местоположение: София / Велико Търново
|
 Re: Интересно поведение на GCC
Принципно няма как да му се подаде нещо което не му е известен размера преди компилация. Затова предполагам е препроцесорна обработката. strlen е друга работа, пък и от масива може да каже колко е дълъг стринга който седи вътре. Но за константни стрингове sizeof ми се струва по-добре, не хаби ресурси.
|
| Вто Ное 12, 2019 3:44 pm |
|
 |
|
ec1832
Ранг: Минаващ
Регистриран на: Пон Ное 11, 2019 6:51 pm Мнения: 2
|
 Re: Интересно поведение на GCC
Всъщност има. В ето този код например: Примерен изход: Това обаче е C99 код, примерът е малко изкуствен, но все пак показва, че не винаги операндът на sizeof е с известен размер по време на компилация.
|
| Вто Ное 12, 2019 6:39 pm |
|
 |
|
TheWizard
Ранг: Форумен бог
Регистриран на: Сря Апр 27, 2005 12:48 pm Мнения: 6094
|
 Re: Интересно поведение на GCC
sizeof(42) 
_________________ main[-1u]={1};
|
| Вто Ное 12, 2019 7:19 pm |
|
 |
|
miro_atc
Ранг: Форумен бог
Регистриран на: Нед Фев 26, 2006 6:52 pm Мнения: 11266 Местоположение: Добрич
|
 Re: Интересно поведение на GCC
Операторите са си оператори и препроцесора не ги бара. В Ц++ операторите могат да се овърлоадват и може да ги пренапишеш така че да връщат каквото решиш. Дали ще се генерира рън тайм код или не зависи от компилатора. Очевидно за базисните sizeof() няма как да се генерира код, тъй като няма изчисления/обработки. Това за кода важи и за стандартните функции, ако нивото на оптимизация е достатъчно и функцията е ясна на ниво компилация, то вместо да я вика компилатора я заменя с резултата.
|
| Вто Ное 12, 2019 7:20 pm |
|
 |
|
slav4o.com
Ранг: Форумен бог
Регистриран на: Нед Яну 01, 2012 8:04 pm Мнения: 2663 Местоположение: София / Велико Търново
|
 Re: Интересно поведение на GCC
@ec1832: main.c:583:19: error: variable length arrays are not supported това съобщение изкарва XC8. Даже някъде бях чел, че дори за локалните променливи е заделено мястото в паметта. За други компилатори вероятно е другояче.
@miro_atc : Пробвах sizeof - не консумира никакъв програмен код. Че е оператор, оператор е, в моят случай обаче явно само препроцесорна обработка прави. Явно, че в моят случай оптимизира винаги...
|
| Вто Ное 12, 2019 11:09 pm |
|
|
Кой е на линия |
Потребители разглеждащи този форум: 0 регистрирани и 2 госта |
|
Вие не можете да пускате нови теми Вие не можете да отговаряте на теми Вие не можете да променяте собственото си мнение Вие не можете да изтривате собствените си мнения Вие не можете да прикачвате файл
|
|