Mst137 Mst137 - 3 months ago 14
C Question

Passing part of a structure in C

I have a structure declared like so:

typedef struct {
char InstrumentDB[128];
char GeneralSettingsDB[128];
char LiveDB[128];
char SystemsDB[128];
} Address;


However when I try to call the function
OpenDatabase(char* filepath, ...)
I get an error. I call it like this:

OpenDatabase(Filepath.InstrumentDB, db);


However when I create a new char array of the same size but in a separate variable not attributed to the structure it works? Why is this? Surely they are of the same type?

EDIT: Filepath.InstrumentDB is declared like this :

Address Filepath;
Filepath.InstrumentDB = "/root/BBBTest/Instruments.db";


And this is the error i get:
error: incompatible types when assigning to type ‘char[128]’ from type ‘char *’

Answer

Invalid Initialization

Your code is invalid:

Address Filepath;
Filepath.InstrumentDB = "/root/BBBTest/Instruments.db";

If I try this with a minimal example, I get this error with LLVM 7.3:

~/tmp> gcc -Wall -pedantic -ansi test.c
test.c:19:24: error: array type 'char [128]' is not assignable
  address.InstrumentDB = "/root/BBBTest/Instruments.db";
  ~~~~~~~~~~~~~~~~~~~~ ^

You are attempting to override a static initializer. The memory for your InstrumentDB field is already allocated at when you create your structure. Instead, simply reuse it by copying the data you need.

Working Minimal Examples

With a Dynamic Copy

This works as intended:

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


typedef struct {
  char InstrumentDB[128];
} Address;

void OpenDatabase(char* filepath) {
  /* do stuff */
  printf("%s\n", filepath);
}


int main(int ac, char **av) {
  Address address;
  strcpy(address.InstrumentDB, "test");
  OpenDatabase(address.InstrumentDB);
}

A Quick Note on String Copy Actions:

C-strings are null-terminated by convention. Note that in the above example I used the strcpy() function for the sake of simplicity. However, should your input string come from a non-static source (ie I/O of any kind like user-input, file input, ...), not be null-termined, or your software be constructed in a way that may allow to modify the intended purpose, you'd want to guard against buffer overflow/overrun errors by using explicit copy actions (for instance strncpy, or strlcpy/lstrcpy, depending on target environments).

Thanks to users StoryTeller and iwin for pointing this out.

With a Static Initialization

Replacing the initialization line in the sample above with this would also work:

int main(int ac, char **av) {
  Address address = {
    "test2"
  };
  OpenDatabase(address.InstrumentDB);
}
Comments