Отговори на тема  [ 35 мнения ]  Отиди на страница Предишна  1, 2, 3  Следваща
Интересно поведение на GCC 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 8:04 pm
Мнения: 2663
Местоположение: София / Велико Търново
Мнение Re: Интересно поведение на GCC
Направих тест

sizeof("TEST") връща 5
sizeof("1234567890") връща 11

Код:
char * sizetest = "TEST";
sizeof(sizetest) връща 2

Код:
char * sizetest = "1234567890";
sizeof(sizetest) връща 2

Код:
char sizetest[12] = {'T','E','S','T',0x00};
sizeof(sizetest) връща 12

Код:
char sizetest[12] = {'1','2','3','4','5','6','7','8','9','0'};
sizeof(sizetest) връща 12

_________________
https://github.com/slav4ocom/


Съб Ное 09, 2019 11:06 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Сеп 26, 2004 9:21 pm
Мнения: 30684
Местоположение: София
Мнение Re: Интересно поведение на GCC
Ами ти с първите два кода декларираш пойнтер към литерал, а след това искаш sizeof на самият пойнтер. Във вторият си декларираш масив като си го определил че е с 12 елемента, и номрлано да ти връща 12. Ако беше char sizetest []="xxx" ще ти върне нещо различно.


Съб Ное 09, 2019 11:32 pm
Профил
Ранг: Напреднал
Ранг: Напреднал

Регистриран на: Вто Май 07, 2019 9:16 pm
Мнения: 434
Местоположение: I bin thinkin’ this bin Gurindji country. We bin here longa time before them Vestey mob.
Мнение Re: Интересно поведение на GCC
slav4o.com написа:
...
Някой виждал ли е компилатор който работи без скоби ?

На семантикс аналайзера все му е тая за скобите, синтактик-анализа ще се обади само в случай че си сложил отваряща но не и затваряща. Ти си тоя който ще реве, ако не слушаш Керниган и парс-дървото ти се изгради в неправилния ред, т.е. - прецидънса на логическите и други оператори няма да се изпълнява в правилния ред и крайния резултат може да е странен и проблема с амбигуити-то на написното -трудно ловим.


Нед Ное 10, 2019 12:08 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Окт 11, 2011 11:53 pm
Мнения: 4582
Местоположение: Brussels / Пловдив
Мнение Re: Интересно поведение на GCC
slav4o.com написа:
... Някой виждал ли е компилатор който работи без скоби ?

Предполагам, ме имаш в предвид {} скоби а не () :)
Префиксните езици нямат скоби (Fort), постфиксните са само скоби (Lisp), инфиксните (C, Pascal, Java, ...) са по средата :D

_________________
Мразя да мразя ...


Нед Ное 10, 2019 12:40 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Пон Ное 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
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: Интересно поведение на GCC
TheWizard написа:
memcmp( command, "TEST", sizeof("TEST")-1 ) :roll:
http://www.cplusplus.com/reference/cstring/memcmp/


проблемът не е какво връща sizeof() а за какво се ползва. За дължина на стринг си има стандартна функция, за сравнение на стрингове също. Функциите за стрингове връщат същия резултат като функциите за памет, но само докато вместо ANSI не се наложи да се ползва някакъв друг енкодинг... В случая вероятно се разчита, че командите ще си останат винаги на английски, ама въпреки всичко по-добре да не се залагат бомбички, защото никога не се знае знае ли се ;-)


Пон Ное 11, 2019 9:23 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 12:48 pm
Мнения: 6094
Мнение Re: Интересно поведение на GCC
:) ам те не гледат какво съм "подчертал" - memcmp
в горните постове компарваха стингове буква по буква
нарочно сложих sizeof("тест")-1 да се види "показателно" кое броя

_________________
main[-1u]={1};


Пон Ное 11, 2019 10:59 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 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 в програмната флаш памет.

_________________
https://github.com/slav4ocom/


Вто Ное 12, 2019 12:26 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 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
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: Интересно поведение на GCC
TheWizard написа:
sizeof() е препроцесор


sizeof() е оператор!


Вто Ное 12, 2019 9:53 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 8:04 pm
Мнения: 2663
Местоположение: София / Велико Търново
Мнение Re: Интересно поведение на GCC
Принципно няма как да му се подаде нещо което не му е известен размера преди компилация. Затова предполагам е препроцесорна обработката.
strlen е друга работа, пък и от масива може да каже колко е дълъг стринга който седи вътре. Но за константни стрингове sizeof ми се струва по-добре, не хаби ресурси.

_________________
https://github.com/slav4ocom/


Вто Ное 12, 2019 3:44 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Пон Ное 11, 2019 6:51 pm
Мнения: 2
Мнение Re: Интересно поведение на GCC
slav4o.com написа:
Принципно няма как да му се подаде нещо което не му е известен размера преди компилация.


Всъщност има. В ето този код например:

Код:
#include <stdio.h>
#include <stdlib.h>

void test(int n)
{
char array[n];
   printf("Array size: %i\n", sizeof array);
}

int main(void)
{
int i;
   srand(896698);
   for (i = 0; i < 10; test(rand()), i ++);
   return 0;
}


Примерен изход:
Код:
Array size: 11924
Array size: 30390
Array size: 20188
Array size: 29113
Array size: 4193
Array size: 17181
Array size: 20859
Array size: 31389
Array size: 27317
Array size: 24427



Това обаче е C99 код, примерът е малко изкуствен, но все пак показва, че не винаги операндът на sizeof е с известен размер по време на компилация.


Вто Ное 12, 2019 6:39 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 12:48 pm
Мнения: 6094
Мнение Re: Интересно поведение на GCC
miro_atc написа:
TheWizard написа:
sizeof() е препроцесор


sizeof() е оператор!



sizeof(42) :)

_________________
main[-1u]={1};


Вто Ное 12, 2019 7:19 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: Интересно поведение на GCC
slav4o.com написа:
Принципно няма как да му се подаде нещо което не му е известен размера преди компилация. Затова предполагам е препроцесорна обработката.
strlen е друга работа, пък и от масива може да каже колко е дълъг стринга който седи вътре. Но за константни стрингове sizeof ми се струва по-добре, не хаби ресурси.


Операторите са си оператори и препроцесора не ги бара. В Ц++ операторите могат да се овърлоадват и може да ги пренапишеш така че да връщат каквото решиш. Дали ще се генерира рън тайм код или не зависи от компилатора. Очевидно за базисните sizeof() няма как да се генерира код, тъй като няма изчисления/обработки. Това за кода важи и за стандартните функции, ако нивото на оптимизация е достатъчно и функцията е ясна на ниво компилация, то вместо да я вика компилатора я заменя с резултата.


Вто Ное 12, 2019 7:20 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 8:04 pm
Мнения: 2663
Местоположение: София / Велико Търново
Мнение Re: Интересно поведение на GCC
@ec1832:
main.c:583:19: error: variable length arrays are not supported
това съобщение изкарва XC8. Даже някъде бях чел, че дори за локалните променливи е заделено мястото в паметта.
За други компилатори вероятно е другояче.

@miro_atc :
Пробвах sizeof - не консумира никакъв програмен код. Че е оператор, оператор е, в моят случай обаче явно само препроцесорна обработка прави. Явно, че в моят случай оптимизира винаги...

_________________
https://github.com/slav4ocom/


Вто Ное 12, 2019 11:09 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 35 мнения ]  Отиди на страница Предишна  1, 2, 3  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 2 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни