-1

Background

  • Writing a library with two kind of functions
    • process array
    • process array char
  • This data structure is accessed by the project inner loop

Situation

I attempt to encapsulate the array declaration with its initialization as a step to keep related code together.

I am aware I will need to pass an array pointer to each function and wonder about performance.

Version 1 :

#include <stdio.h>

typedef struct char_array {
    unsigned char uchar;                
    char          achar;

} char_array;

#define CA_SIZE 1000000 

char_array *ptr_array_one;
char_array *ptr_array_two;

main() {
    char_array_init(ptr_array_one);   
    char_array_search(ptr_array_one);

    char_array_init(ptr_array_two);
    // etc.
}

char_array_init(struct char_array *ptr_array) {
    static char_array ptr_array[CA_SIZE];

    ptr_array[0].uchar= 'a';
    ptr_array[5].uchar= 'b';

    printf("%c\n\n", ptr_array[0].uchar);
}

char_array_search(struct char_array *ptr_array){
    printf("%c\n\n", ptr_array[5].uchar);
}

I also tried Version 2 :

    #include <stdio.h>

    typedef union char_array {
        unsigned char uchar;                                                                
        char        achar;
    } char_array;

    #define CA_SIZE 1000000 

    char_array *ptr_array_one;

    main() {

        ptr_array_one = char_array_init(ptr_array_one);   

    }

    union * char_array_init(union char_array ptr_array) {

            static char_array char_array[CA_SIZE];

                char_array[0].uchar= 'a';
                char_array[5].uchar= 'b';

                printf("%c\n\n", char_array[0].uchar);
                return &char_array;
    }

I cannot get this to compile either.

Question

I am looking for a solution to achieve this coding attempt, inspired by this code

I am trying to dynamically declare two or more static arrays, for a pointer (ptr_array_one, ptr_array_two, ...) to reference them.

char_array_init()

  • to declare and initialize a different array each time it is called
  • to place array address into ptr_array_one, ptr_array_two, ...

char_array_search() intends to access a specific array, hence receives a char_array structure pointer as argument.

This code is my attempt to isolate the sought feature rather than the actual inner loop.

This code does not compile successfully. It's the best I can come up with.

Community
  • 1
  • 1
OneArb
  • 453
  • 2
  • 14
  • 3
    I don't understand what you are asking, but perhaps this link will help: http://stackoverflow.com/questions/3965279/opaque-c-structs-how-should-they-be-declared – Be Kind To New Users Nov 06 '14 at 00:12
  • 5
    This makes no sense. Why are you passing an uninitialized pointer into `char_array_init()`, and then declaring a static array of the same name which is never used again? What is this "inner loop" of which you speak? Why don't any of your functions have return types? It's not the 1980s any more. Why define a `struct` called `char_array` that only has a single `unsigned char` in it, and no array? It's all rather mystifying, and impossible to tell what you're asking. – Crowman Nov 06 '14 at 00:14
  • Note that you never allocate memory for `ptr_array_one` or `ptr_array_two` to point at, so any attempt to use them leads to undefined behaviour (usually a crash). – Jonathan Leffler Nov 06 '14 at 00:48
  • 1
    If you have GCC as your compiler (or `clang`), you would do well to compile with `-Wshadow` (which would point out the problem that @PaulGriffiths describes) -- as well as general options like `-Wall -Wextra -Werror` which will keep you honest (or from making mistakes; take your pick). – Jonathan Leffler Nov 06 '14 at 00:54
  • 1
    What is your problem? What have you attempted? What is not working? What is expected? – smac89 Nov 06 '14 at 00:59
  • @Smac89 1) I want a function to allocate memory and initialize an array 2) I cannot cast arguments properly 3) 2 arrays I can access through another function – OneArb Nov 06 '14 at 02:24
  • @Paul Griffiths C wasn't invented yet when I went to college ... Good catch ! The struct is really an union – OneArb Nov 06 '14 at 02:28
  • @Jonathan Leffler This is the smallest step I can think of. I tried the switches you recommended. I still cannot figure out how to cast the pointers properly : error: cast to union type from type not present in union ptr_array_one = (char_array ) char_array_init(ptr_array_one); I declare ptr_array_one as a pointer to char_array but I can't seem to return and store the union array address in it. (compiling the second example) – OneArb Nov 06 '14 at 02:41
  • @Michael Potter I am trying to set up a very basic TDD - some better than none - isolate, organize. Semantically, allocate array memory and initialize array go together in my mind, so I am looking for some code to express it. The link you provide along the initial responses to my question seem to point I am venturing outside standard practice. – OneArb Nov 06 '14 at 03:05

2 Answers2

1

Starting from this code of yours (with the function reindented but otherwise unchanged):

#include <stdio.h>

typedef union char_array {
    unsigned char uchar;                                                                
    char        achar;
} char_array;

#define CA_SIZE 1000000 

char_array *ptr_array_one;

main() {

    ptr_array_one = char_array_init(ptr_array_one);   

}

union * char_array_init(union char_array ptr_array) {

    static char_array char_array[CA_SIZE];
    char_array[0].uchar= 'a';
    char_array[5].uchar= 'b';

    printf("%c\n\n", char_array[0].uchar);
    return &char_array;
}

I would immediately write it like this:

#include <stdio.h>

typedef union char_array
{
    unsigned char uchar;
    char achar;
} char_array;

#define CA_SIZE 1000000

union char_array *char_array_init(union char_array **ptr_array);

char_array *ptr_array_one;
char_array *ptr_array_two;

int main(void)
{
    ptr_array_two = char_array_init(&ptr_array_one);
    printf("one: %c (%p)\n", ptr_array_one->uchar, (void *)ptr_array_one);
    printf("two: %c (%p)\n", ptr_array_two->uchar, (void *)ptr_array_two);
    return 0;
}

union char_array *char_array_init(union char_array **ptr_array)
{
    static char_array char_array[CA_SIZE];

    char_array[0].uchar = 'a';
    char_array[5].uchar = 'b';

    printf("%c\n\n", char_array[0].uchar);
    *ptr_array = char_array;
    return char_array;
}

This compiles cleanly using:

gcc -g -O3 -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
    -Werror tddoop.c -o tddoop

and runs:

a

one: a (0x104e9d040)
two: a (0x104e9d040)

Since the two pointers end up pointing at the same (enormous) static array, it isn't surprising that the printing prints the same pair of values twice.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • The two pointers being identical is the reason why I gave up on the version 2, as I assumed that would be the expected result. Is runtime static memory allocation possible in gcc altogether ? Second side effect in your solution : the array is global whereas I am trying to achieve some level of lexical scoping. – OneArb Nov 06 '14 at 05:09
  • @OneArb: Have you come across dynamic memory allocation and `malloc()` and `free()` yet? – Jonathan Leffler Nov 06 '14 at 05:11
  • The array size is known at compile time, it's really meant to be larger than one megabyte. Static seems the way to go. The structs/opaque pointers link - you provided in your original comment - to achieve encapsulation seems the appropriate solution. It is not clear why it does not achieve it. – OneArb Nov 06 '14 at 05:26
  • Will there be just one array, or will there be many arrays. Will you know exactly how many arrays? How much bigger than 1 MB are you thinking of? Are you using a 32-bit or 64-bit machine? – Jonathan Leffler Nov 06 '14 at 05:30
  • The original array is 83 MB - the worst case scenario - then I'll compress it onto the second array. The second array could also be used as an overflow to the first one. The initial target language is REBOL / Red, so it could be either 32-bit or 64-bit. – OneArb Nov 06 '14 at 05:51
0

Partial answer :

This article proposes a solution to encapsulate in C

  • type safe
  • hides data structures from the API user
  • does not require typedef on the struct
OneArb
  • 453
  • 2
  • 14