C++ масив
15 отговора
961 прегледа
C++ масив
Досега не зе бях замислял за това, но случайно се сблъсках с този въпрос:
един масив ( от char ) . Масива се дефинира в някакъв метод, в същия метод резултата от sizeof за този масив връща броя на байтовете заделени за масива. Подаден като параметър на някакъв метод, резултата sizeof за този масив връща размера на указатея, който е с коректната стойност 4 байта, но не и размера на масива.
Имате ли обяснение за това ?
// code
void fun1();
void fun2(char a[]);
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
fun1();
return 0;
}
void fun1()
{
char a[] = "Hello Africa";
printf("sizeof a = %d\tstrlen a = %d\n", sizeof(a), strlen(a));
fun2(a);
}
void fun2(char a[])
{
printf("sizeof a = %d\tstrlen a = %d\n", sizeof(a), strlen(a));
}
// end code
result:
-----------------------------
sizeof a = 13 strlen a = 12
sizeof a = 4 strlen a = 12
Press any key to continue
един масив ( от char ) . Масива се дефинира в някакъв метод, в същия метод резултата от sizeof за този масив връща броя на байтовете заделени за масива. Подаден като параметър на някакъв метод, резултата sizeof за този масив връща размера на указатея, който е с коректната стойност 4 байта, но не и размера на масива.
Имате ли обяснение за това ?
// code
void fun1();
void fun2(char a[]);
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
fun1();
return 0;
}
void fun1()
{
char a[] = "Hello Africa";
printf("sizeof a = %d\tstrlen a = %d\n", sizeof(a), strlen(a));
fun2(a);
}
void fun2(char a[])
{
printf("sizeof a = %d\tstrlen a = %d\n", sizeof(a), strlen(a));
}
// end code
result:
-----------------------------
sizeof a = 13 strlen a = 12
sizeof a = 4 strlen a = 12
Press any key to continue
Re: C++ масив
"Обяснение" не е нужно, това е поведението, което стандартът специфицира.
Ето един цитат от MSDN: "When the sizeof operator is applied to an array, it yields the total number of bytes in that array, not the size of the pointer represented by the array identifier. To obtain the size of the pointer represented by the array identifier, pass it as a parameter to a function that uses sizeof.".
В твоя случай, тази декларация: "char a[] = "Hello Africa";" е еквивалентна на " char a[13] = "Hello Africa";". Затова и получаваш sizeof 13. От друга страна, декларацията "void fun2(char a[])" е еквивалентна на "void fun2(char *a)". Това мисля изяснява нещата.
Ето един цитат от MSDN: "When the sizeof operator is applied to an array, it yields the total number of bytes in that array, not the size of the pointer represented by the array identifier. To obtain the size of the pointer represented by the array identifier, pass it as a parameter to a function that uses sizeof.".
В твоя случай, тази декларация: "char a[] = "Hello Africa";" е еквивалентна на " char a[13] = "Hello Africa";". Затова и получаваш sizeof 13. От друга страна, декларацията "void fun2(char a[])" е еквивалентна на "void fun2(char *a)". Това мисля изяснява нещата.
Re: C++ масив
наскоро някой ми беше разправял за предаване на масив във стека нещо, как по рано го имало после било премахнато щото много неразумно го ползвали. работата е там че при предаване на масив би трябвало да се копира целия в стека. поради това че много от програмистите не го съзнават това, то е направено отстъпление от принципа, и ако се декларира void func(char a[200]) то компилатора предава само указателя. това донякъде ме дразни, защото изразява една по-глобална тенденция да се усложнява живота на квалифицираните, в полза на неквалифицираните. верно е че в почти всички случаи да се предава по стойност масив е чиста лудост, но все пак принципа си е принцип. ако исках само указател, щях да напиша char *a. поне да го даваше като грешка, а то си трае. в края на краищата който иска да пише без да се интересува какво става отдолу, има си java i VB.
Re: C++ масив
Imash predvid kato w Turbo/Borland Pascal-a? (Delphi-to)? Ne znam dali e standartno tova i za ostanalite Pascali-i de...
No pri tjah se podawashe w steka masiva, dokolkoto si spomnjam.
Naistina izglezhda razumno ako e napisano
char func( int a[100] ) - da se podadat neshta w steka....
Problema, obache e sus tova KOJ OSVOBOZHDAWA steka:
Pri Pascal (Borland/Turbo), ili wuobshte pri __pascal, ili __stdcall callovete- tam steka se osvobozhdawa ot funckiata - tja si popwa i restorwa ebp/esp.
Pri C, ili po-tochno pri _cdecl call-a - tam tozi kojto izwikwa opravja steka - funckiata ne se grizhi za tova.
Mozhe bi e svurzano s poslednite dve neshta, no ne mi e mnogo jasno - ne wizhdam direktna vruzka... Njakoi ako se seshta neshto po-tochno...
No pri tjah se podawashe w steka masiva, dokolkoto si spomnjam.
Naistina izglezhda razumno ako e napisano
char func( int a[100] ) - da se podadat neshta w steka....
Problema, obache e sus tova KOJ OSVOBOZHDAWA steka:
Pri Pascal (Borland/Turbo), ili wuobshte pri __pascal, ili __stdcall callovete- tam steka se osvobozhdawa ot funckiata - tja si popwa i restorwa ebp/esp.
Pri C, ili po-tochno pri _cdecl call-a - tam tozi kojto izwikwa opravja steka - funckiata ne se grizhi za tova.
Mozhe bi e svurzano s poslednite dve neshta, no ne mi e mnogo jasno - ne wizhdam direktna vruzka... Njakoi ako se seshta neshto po-tochno...
Re: C++ масив
Мисля, че няма такава връзка.
А в C/C++, който иска да предава масиви по стойност, да ги вкара в struct-ура.
А в C/C++, който иска да предава масиви по стойност, да ги вкара в struct-ура.
абе то начини има
може и да си го копираш, ама мен ме дразни че се нарушава правило.
Re: C++ масив
не се излагай, достатъчно е само да се спомене, че sizeof се смята по време на компилация, а не по време на изпълнение.
Re: C++ масив
вярно, бре
то сичко идва от това: char* и char [13] ....
т.е. ако декларираш ф-ята така: void fun(char a[13]); sizeof ще върне 13 ...
то сичко идва от това: char* и char [13] ....
т.е. ако декларираш ф-ята така: void fun(char a[13]); sizeof ще върне 13 ...
Re: аха, как пък не
не дава, аз снощи го пробвах
Все си е 4.
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Все си е 4.
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Re: C++ масив
Ako imash slednia kod:
void fcall1()
{
char aaa[10] = "string";
fun(aaa);
}
void fcall2()
{
char bbb[15] = "drug string";
fun(bbb);
}
void fun(char a[])
{
printf("sizeof a = %d\tstrlen a = %d\n", sizeof(a), strlen(a));
}
w compile time kompilatora kak da zamesti sizeof(a) wuw fun(char a[]) ednowremenno s 10 i 15
void fcall1()
{
char aaa[10] = "string";
fun(aaa);
}
void fcall2()
{
char bbb[15] = "drug string";
fun(bbb);
}
void fun(char a[])
{
printf("sizeof a = %d\tstrlen a = %d\n", sizeof(a), strlen(a));
}
w compile time kompilatora kak da zamesti sizeof(a) wuw fun(char a[]) ednowremenno s 10 i 15
Re: C++ масив
Много просто - големината на far pointer е 4 байта, независимо към какво сочи. Ти другите мнения не чете ли?
Както се оказва sizeof() наистина се изчислява при компилацията. Има обаче нещо гнило в Дания. Аз се чудех как ще се определи големината на обект при полиморфизъм. Затова написах следното тестче:
//***********************************************
// Trial.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <assert.h>
//===================================================================
class base {
double dBase;
public:
base(double Base) { dBase = Base; }
};
//===================================================================
class child1:public base {
int i1;
public:
child1(double Dbl,int Int1):base(Dbl) { i1 = Int1; }
};
//===================================================================
class child2:public base {
double d1;
public:
child2(double Dbl,double Dbl1):base(Dbl) { d1 = Dbl1; }
};
//===================================================================
int main(int argc, char* argv[])
{
base Bs(42);
child1 Ch1(42,42);
child2 Ch2(42,42);
base *pBs = new base(42);
base *pCh1 = new child1(42,42);
base *pCh2 = new child2(42,42);
printf("Non-referenced sizes: B = %d, Ch1 = %d, Ch2 = %d\n",sizeof(Bs),sizeof(Ch1),sizeof(Ch2));
printf("Referenced sizes: B = %d, Ch1 = %d, Ch2 = %d\n",sizeof(*pBs),sizeof(*pCh1),sizeof(*pCh2));
while(!kbhit());
delete pBs; delete pCh1; delete pCh2;
return 0;
}
//***********************************************
Та, резултатът е следния:
Non-referenced sizes: B = 8, Ch1 = 16, Ch2 = 16
Referenced sizes: B = 8, Ch1 = 8, Ch2 = 8
Асемблерният код преди извикване на printf е съответно:
push 10h
push 10h
push 8
push 8
push 8
push 8
и това за Debug mode, не за Release. От това следват две неща:
1. sizeof() наистина се изчислява при компилацията
2. sizeof() бърка когато става дума за полиморфизъм, като ти връща големината на класа за които е обявен поинтера. а не на обекта към който сочи в действителност. Следователно ако ти трябва големината на обекта в run-time трябва да ползваш друга технология.
Със здраве!
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Както се оказва sizeof() наистина се изчислява при компилацията. Има обаче нещо гнило в Дания. Аз се чудех как ще се определи големината на обект при полиморфизъм. Затова написах следното тестче:
//***********************************************
// Trial.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <assert.h>
//===================================================================
class base {
double dBase;
public:
base(double Base) { dBase = Base; }
};
//===================================================================
class child1:public base {
int i1;
public:
child1(double Dbl,int Int1):base(Dbl) { i1 = Int1; }
};
//===================================================================
class child2:public base {
double d1;
public:
child2(double Dbl,double Dbl1):base(Dbl) { d1 = Dbl1; }
};
//===================================================================
int main(int argc, char* argv[])
{
base Bs(42);
child1 Ch1(42,42);
child2 Ch2(42,42);
base *pBs = new base(42);
base *pCh1 = new child1(42,42);
base *pCh2 = new child2(42,42);
printf("Non-referenced sizes: B = %d, Ch1 = %d, Ch2 = %d\n",sizeof(Bs),sizeof(Ch1),sizeof(Ch2));
printf("Referenced sizes: B = %d, Ch1 = %d, Ch2 = %d\n",sizeof(*pBs),sizeof(*pCh1),sizeof(*pCh2));
while(!kbhit());
delete pBs; delete pCh1; delete pCh2;
return 0;
}
//***********************************************
Та, резултатът е следния:
Non-referenced sizes: B = 8, Ch1 = 16, Ch2 = 16
Referenced sizes: B = 8, Ch1 = 8, Ch2 = 8
Асемблерният код преди извикване на printf е съответно:
push 10h
push 10h
push 8
push 8
push 8
push 8
и това за Debug mode, не за Release. От това следват две неща:
1. sizeof() наистина се изчислява при компилацията
2. sizeof() бърка когато става дума за полиморфизъм, като ти връща големината на класа за които е обявен поинтера. а не на обекта към който сочи в действителност. Следователно ако ти трябва големината на обекта в run-time трябва да ползваш друга технология.
Със здраве!
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Re: C++ масив
Абе аре са, ем цветен телевизор, ем па и да работи...
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Re: C++ масив
да, sizeof дава големината според декларацията на указателя. иначе не можеш да му хванеш края. а да кажеш че бърка е малко пресилено. в края на краищата ако направиш
int *ip;
char c;
ip=(int*)&c;
printf("%d",sizeof(*ip));
нали не очакваш да ти напише 1...
а и като се замисли човек, то не е функция. ако беше, какъв тип е аргумента и? никакъв, може да сложиш име на клас, може да сложиш инстанция, може да сложиш всичко.
int *ip;
char c;
ip=(int*)&c;
printf("%d",sizeof(*ip));
нали не очакваш да ти напише 1...
а и като се замисли човек, то не е функция. ако беше, какъв тип е аргумента и? никакъв, може да сложиш име на клас, може да сложиш инстанция, може да сложиш всичко.
Re: C++ масив
Ммм прав си за бъркането, не е коректно изказването... Аз досега изобщо не бях се замислял за тия неща, sizeof го ползвам изключително за structs и unions.
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Мечтата е мисъл, мисълта е идея, всяка идея се реализира. Аз не мечтая, а реализирам идеите си.
Re: C++ масив
he, mi mnogo qsno che ne e funkciq 

sizeof e klyuchova duma(sintaktichna edinica v ezila, bla-bla...), sushto kato if, for, struct i t.n.