user559865
user559865

Reputation: 1

Simple C array issues


#include <stdio.h>

#define MEM_SIZE 16

typedef struct memory_contents{
 unsigned char mem[MEM_SIZE]; /* memory */
} mem;

mem init(char prog[]){
 mem chip = {prog};
 return chip;
}

int main(int argc, char *argv[]){
 char memory[MEM_SIZE] = {0}; /* zero out whole array */
 mem chip = init(memory);

 printf("%d\n", chip.mem[0]);
    return 0;
}

Am I right in thinking that what this code does (specifically, the init function) is try to put the address of the variable 'memory' into the struct's array? (and hence this is why it's printing a non-zero value)

What I'm trying to achieve is to initialise the struct such that the struct's mem array is the prog[] parameter. What's the preferred, or best, way of doing this? I could make the struct's mem a pointer to the first element of an array of size MEM_SIZE, but I feel that might cause problems: if I change the memory array in main later down the line, it'll change the values in chip's array too.

Upvotes: 0

Views: 321

Answers (5)

user411313
user411313

Reputation: 3990

For your struct you can use the implicit struct-content-copy like:

mem init(char *prog){
 return *(mem*)prog;
}

int main(int argc, char *argv[]){
 char memory[MEM_SIZE] = {0xAA,0xBB,0xCC,0xDD}; /* non zero test values */

 mem chip = init(memory);
 printf("%02X%02X%02X%02X\n",chip.mem[0],chip.mem[1],chip.mem[2],chip.mem[3]);

 memory[1]=0;
 chip = init(memory);
 printf("%02X%02X%02X%02X\n",chip.mem[0],chip.mem[1],chip.mem[2],chip.mem[3]);

 return 0;
}

Upvotes: 0

tperk
tperk

Reputation: 91

All of the above are recommended ways of copying data from a buffer into a contained buffer defined in a struct.

And, to answer your question - yes. You're initializing the array with the pointer value. Initializing the array like you did in main with "memory": char memory[MAX_SIZE] = { 0 }; // array intialization.

Performing a memcpy() is the preferred way of doing this. Also - it's bad practice returning a local struct from a function - the preferred way is to allocate an object on the heap and do a memcpy. (Though the compiler could optimise this out - with the extra copying) It's just horrible practice.

If you know the structure of the array at compile time: Other possibilities are c99 struct initializations (usually done within kernel mode): mem_t memObj = { .mem = { 1, 2, 3, 4, 5 } }; or simply: mem_t memObj = { 1, 2, 3, 4, 5 }; (in your example, since it's the only member)

Note: When doing array initializations, it's similar to zero'ing out the rest of the elements in the array - could be not what you were expecting/wanted.

Upvotes: 0

Vikram.exe
Vikram.exe

Reputation: 4585

Here is the recommended way of doing this:

#include <stdio.h>

#define MEM_SIZE 16

typedef struct memory_contents{
 unsigned char mem[MEM_SIZE]; /* memory */
} mem_t;

mem_t* init (char* arr)
{
    mem_t* info = (mem_t*) malloc (sizeof (mem_t));
    if (!info)
    return NULL:    /* No memory */

    memcpy (&info->mem, arr, MEM_SIZE);
    return info;
}

int main(int argc, char *argv[])
{
    unsigned char memory[MEM_SIZE] = {1,2,3,4,5,6,0};
    mem_t* chip = init (memory);
    if (!chip)
    return ENOMEM;

    printf("values: %d %d\n", chip->mem[0], chip->mem[1]);

    if (chip)
    free (chip);

    return 0;
}

one more point to note: Try not have the structure field member name and structure name same. They might cause a lot of conflicts.

Upvotes: 1

smokingcode
smokingcode

Reputation: 1

  1. Use memcpy to copy data
  2. Allocate new memory in func init, the 'chip' will be recovered when the func init end.

Upvotes: 0

user541686
user541686

Reputation: 210515

You can't change the struct's mem pointer because it's not a normal pointer -- the name mem is just a name for the address of that field. Don't initialize arrays using { ... } notation; it's just hard to read and confusing (it certainly confused me...). Use memcpy instead.


Edit:

Your code doesn't compile with my compiler:

error C2440: 'initializing' : cannot convert from 'char []' to 'char'
    This conversion requires a reinterpret_cast, a C-style cast or function-style cast

(The error is at this line: mem chip = {prog};)

I was at first confused at why your code even compiled, and after checking it here, it makes sense: Like I stated above, you're trying to assign an array/pointer to mem, which is not allowed because mem is simply a name for the address of the array, not a pointer that can change. So you have to use memcpy to copy the elements.

Upvotes: 0

Related Questions