Re: Maximum char array size?

From: Roman Ziak (roman_at_nospam.com)
Date: 06/14/04


Date: Sun, 13 Jun 2004 21:40:39 -0400


> My home platform is linux+gcc. I need to be compatable with the
> Windows 32-bit world, but not necessarily ancient real-mode DOS. If the
> max size is implementation-specific, is there a standard variable that I
> can look up at run/compile time? Also, are there any advantages to
> malloc(), versus declaring an array at compile time (other than the need
> to macro-ize the array dimension in a regular declaration)?

I believe there would be the difference in compiled executable size
(depending on how GNU linker handles uninitialized sections, not sure).

And the other difference is that the malloc()-ed multidimensional arrays
are little painful to work with. In the example at the end of this message,
I did not get anywhere before I declared the new type ARRAY2.

The third difference is that Array1 (from example below) will be allocated
most
likely on stack and Array2 in the heap.

I did couple benchmarks with the example below using BCC, VC++, LCC, GCC
and DMC (Digital Mars Compiler) on WinXp. The DMC result is not here since
downloadable free version does not produce assembly directly, but I verified
by
disassembler that access to dynamic array is 2 instructions and static only
1.

I was able to achieve performance optimisations for static and dynamic array
with
GCC and LCC compilers only. Good work Jacob :)

Roman

**************** BCC

The following was compiled with "bcc32 -S test.c" (Borland C++ 5.5)
Seems to have a performance hit in the pointer version. Optimizations
using "-Ox" did not seem to help the access Array2 and the compiler
kept realoding registers with *[ebp-4] value (address of allocated Array2)
although it could reuse the same register ecx.

   ; Array1[0][0] = 100;
   ;
 mov dword ptr [ebp-108],100

 ...

   ; Array2[0][0] = 100;
   ;
 mov ecx,dword ptr [ebp-4]
 mov dword ptr [ecx],100
   ;

**************** VC++

The following was compiled with "cl /Fa test.c" (MS VC++ 13.10.2179)
The compiler behaved same as Borland, i.e. Array2 took 2 instructions
rather than 1 for Array1. Optimizations using "/Ox" did not help and
compiler kept reloading the register with address of Array2.

 mov DWORD PTR _Array1$[ebp], 100 ; 00000064H

...

 mov ecx, DWORD PTR _Array2$[ebp]
 mov DWORD PTR [ecx], 100 ; 00000064H

**************** LCC

The following was compiled using "lcc -S -O test.c" (Jacob Navia compiler
based
on Chris Fraser and David Hanson research compiler)
The non-optimized version did look similar to Borland and MS, but
optimization
made access to both arrays same:

before "-O"

; 39 Array1[1][0] = 200;
 movl $200,-76(%ebp)
...
; 44 Array2[1][0] = 200;
 movl -4(%ebp),%edi
 movl $200,24(%edi)

after "-O"

; 39 Array1[1][0] = 200;
 movl $200,-76(%ebp)
...
; 44 Array2[1][0] = 200;
 movl $200,24(%eax)

**************** GCC

The following was compiled with "gcc -S -O test.c" (GCC 3.2 mingw special
20020817-1)

 movl $100, -120(%ebp)
 movl $200, -96(%ebp)
...
 movl -124(%ebp), %eax
 movl $100, (%eax)
 movl -124(%ebp), %eax
 movl $200, 24(%eax)

The following was compiled with "gcc -S -fexpensive-optimizations -O3
test.c" ...

 movl $100, -120(%ebp)
 movl $200, -96(%ebp)
 movl $300, -72(%ebp)
 movl $400, -36(%ebp)
 movl $100, (%eax)
 movl $200, 24(%eax)
 movl $300, 48(%eax)
 movl $400, 84(%eax)

**************** TEST.C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NROW 4
#define NCOL 6
#define CELLS (NROW*NCOL)

void PrintArray(char *name, int *array, int ncol, int nrow)
{
    int i,j;

    printf("\n%s = {\n", name);

    for(i=0; i<nrow; i++)
    {
        for(j=0; j<ncol; j++)
            printf("%4d,",array[i*ncol+j]);
        printf("\n");
    }

    printf("};\n");
}

typedef int ARRAY2[NCOL];

int main(int argc, char *argv[])
{
    int Array1[NROW][NCOL];
    ARRAY2 *Array2;
    int i, j;

    Array2 = (ARRAY2*)malloc(CELLS*sizeof(int));
    printf("Allocated @ 0x%08x, &i=0x%08x, &j=0x%08x, &Array1=0x%08x,
&Array2=0x%08x\n", Array2, &i, &j, &Array1, &Array2);
    memset(Array1,0,CELLS*sizeof(int));
    memset(Array2,0,CELLS*sizeof(int));

    Array1[0][0] = 100;
    Array1[1][0] = 200;
    Array1[2][0] = 300;
    Array1[3][3] = 400;

    Array2[0][0] = 100;
    Array2[1][0] = 200;
    Array2[2][0] = 300;
    Array2[3][3] = 400;

    PrintArray("static Array1", (int*)Array1,NCOL,NROW);
    PrintArray("dynamic Array2", (int*)Array2,NCOL,NROW);

    return 0;
}



Relevant Pages

  • Re: Error handling library
    ... which lets the compiler catch out-of-range usage. ... and assuming that a higher int means "more dangerous error" ... with a comment warning that one is used as an index into the array ... languages while running (an array of languages, ...
    (comp.lang.c)
  • Re: On VLAs and incomplete types
    ... I don't understand how a variable is handled by the compiler in ... declaring a VLA. ... an array must be declared with an ... int x; ...
    (comp.lang.c)
  • Re: max size of ptr array
    ... you'll get a compiler error. ... number you are allowed type in the brackets is exactly 536870911. ... int main{ ... And since an int requires 4 "bytes" plus the fact that your array is ...
    (microsoft.public.vc.language)
  • Re: max size of ptr array
    ... you'll get a compiler error. ... number you are allowed type in the brackets is exactly 536870911. ... int main{ ... And since an int requires 4 "bytes" plus the fact that your array is ...
    (microsoft.public.vc.language)
  • random number code
    ... Will it really compile exactly the same as mingw compiler used ... // initialization of static private members ... MSBs of the seed affect only MSBs of the array ... // constructor with 32 bit int as seed ...
    (comp.lang.cpp)