Howto public struct

Hello,
I am trying to get public struct to whole project which data should be accessed from everywhere like is possible in C, but have problems to do that.

I have declaration in header file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef GENERAL_H_
#define GENERAL_H_

struct _ini
{
    char user[40];
    char password[40];
    char database[40];
    char server[40];
    char port[40];
};
struct _ini ini;
int connectiondata();

#endif 


Then I have function "connectiondata" in one file:
1
2
3
4
5
6
7
8
9
10
int connectiondata()
{
    strcpy(ini.user, "thatsme");
    strcpy(ini.password, "12345");
    strcpy(ini.database, "mydatabase1");
    strcpy(ini.server, "localhost");
    strcpy(ini.port, "3200");

    return 0;
}


And finally, usage of function and data in main module where header is included also:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DBconn* DB_connect(char* database)
{
    connectiondata();

    DBconn *conn;
    char connection_str[256];
    sprintf(connection_str, "%s%s %s%s %s%s %s%s %s%s",
            "user=", ini.user,
            "password=", ini.password,
            "dbname=", ini.database,
            "host=", ini.server,
            "port=", ini.port);

    conn = DBconnect(connection_str);
    return conn;
}


But after returning from connectiondata I havent data in ini structure.

How to achieve that in general, if possible out of classes?
Or this is not possible to do such way in C++?
Last edited on
I am trying to get public struct to whole project which data should be accessed from everywhere like is possible in C, but have problems to do that.
It is possible to do exactly like it was possible in C. Code you have shown will not work in C.
I suppose you want global variable of type _ini. If ypu want an OO approach, you probably should look into Singletone pattern: it was created to make sure tht there could be only one global accessible variable.

Also I suggest to read more about variables, their visibility and storage duration. You clearly have problems with that.
If I wouldn't have beginning problems what would I do here?

I try many ways to achieve that.
Between others to pass structure as an agument:
 
    connectiondata(_ini ini);


That says that "expected primary expression before ini".

Please CONCRETE help.
beginplus2 wrote:
But after returning from connectiondata I havent data in ini structure.


That's because the ini variable inside the function is local to that function - it doesn't affect any other variables elsewhere.

You could send a reference to a object of type _ini to the connectiondata function - then it's data will be changed.

beginplus2 wrote:
How to achieve that in general, if possible out of classes?


Sure you can do this with classes - have a read of the classes section of the tutorial on this site (top left of this page) . If you do this correctly - with a separate header file & .cpp file, you can include the header file into whichever .cpp file needs to use it.

If you have a class - then the connectiondata function could be a constructor & the DBconnect function a member of the class, the variables it uses should be private data members of the class.

Btw, did you intend for the DBconnect function to be recursive?

You also need a constructor & public functions which make up the interface for the class. Don't be tempted to have a get / set function for every member of the class - particularly set functions which are straight assignment are very bad news.

HTH
I do a minimal changes to my code.
It is not true that this code don't work in C and it is true that this code work in C++!

During compiling I get message:

C:\programs\[PG32\mytry.cpp|12|multiple definition of `ini'
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef GENERAL_H_
#define GENERAL_H_

struct _ini
{
    // ...
};

// struct _ini ini; // *** change this; it is a definition of an object with external linkage
typedef struct _ini ini; // this is probably what you want to do.

#endif 


And change the name _ini to (say) connection_data
We should not be having any name beginning with a leading underscore at global scope.
The problem is that object ini was defined twice. The first its definition is in the file where you defined function connectiondata because you included the header with the object definition in this file. The second its definition is in the file where there is main function because you again included the same header file.
Some linkers when they see two definitions of the same object with external linkage convert such an object as having internal linkage. As the result you get two objects of the same type and with the same name that are in fact different and are not visible outside compilation units where they are defined.
So function connectiondata changes the object that is in the compilation unit where there is the definition of the function. At the same time the other object with the same name that is in main was not changed.
To correct the situation you should write in the header

extern struct _ini ini;

and in the module with the function definition of connectiondata write

struct _ini ini;



Last edited on
@JLBorged, vlad from moscow, thank's for helping.
I am very sory but both doesn't work (typedef and extern).

Now we have such stuation:
Header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef GENERAL_H_
#define GENERAL_H_

struct cdat
{
    char user[40];
    char password[40];
    char database[40];
    char server[40];
    char port[40];
};
extern struct cdat ini;
int connectiondata();

#endif  /* GENERAL_H_ */ 


File with function "connectiondata":
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "general.h"

struct cdat ini;

int connectiondata()
{
    strcpy(ini.user, "thatsme");
    strcpy(ini.password, "12345");
    strcpy(ini.database, "mydatabase1");
    strcpy(ini.server, "localhost");
    strcpy(ini.port, "3200");

    return 0;
}


And main file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "general.h"

DBconn* DB_connect(char* database)
{
    DBconn *conn;
    char connection_str[256];
    sprintf(connection_str, "%s%s %s%s %s%s %s%s %s%s",
            "user=", ini.user,
            "password=", ini.password,
            "dbname=", ini.database,
            "host=", ini.server,
            "port=", ini.port);

    conn = DBconnect(connection_str);
    return conn;
}


That compiles with no errors but still don't brings data from "connectiondata" to "DB_connect".

Any further help will be appreciated.
Last edited on
Return the initialized struct from connectiondata()
Use the returned struct in DB_connect()

C code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*int*/ struct cdat connectiondata()
{
    struct cdat ini;
    
    strcpy(ini.user, "thatsme");
    // ...

    return ini ; // ***
}

DBconn* DB_connect( char* database )
{
    struct cdat ini =  connectiondata() ;
    // ...
}


Or use the global struct ini instead of defining different local variables in different functions.
Last edited on
It doesn work because you are doing stupidy.

Why did you declare the local structure in function connectiondata?

1
2
3
4
5
6
7
8
9
10
11
12
int connectiondata()
{
    struct cdat ini;
    
    strcpy(ini.user, "thatsme");
    strcpy(ini.password, "12345");
    strcpy(ini.database, "mydatabase1");
    strcpy(ini.server, "localhost");
    strcpy(ini.port, "3200");

    return 0;
}


How does it relate with the global structure

extern struct cdat ini;
?

You should in file (not in the function itself) where the function is defined include line

struct cdat ini;

End of course the header file also must be included in this file.

Is it clear?

The header contains the common declaration of the global structure object for all modules where the object will be used. And only one module will contain the definition of the object.

extern struct cdat ini; - is a declaration

struct cdat ini; - is a definition
Last edited on
JLBorges, that one works! Thank you very much:)
struct cdat ini = connectiondata();
---

Vlad, sorry, this is my starting touch with C++, but I have some experience with C so I am included header as needed in both files.

I declared local structure in function by mistake and ununderstanding.
Now I am repair example by your advices and it is shown above, (I repair previous post).
It compiles OK but don't transfer data. What more can I do to get it working?
> that one works!
> struct cdat ini = connectiondata();

Now throw out garbage that you don't need. Keep the program clean.

From the header: // extern struct cdat ini;
From the implemenation file: // struct cdat ini; at global scope.

If you are programming in C++, you can the struct keyword:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cdat connectiondata()
{
    cdat ini;
    
    strcpy(ini.user, "thatsme");
    // ...

    return ini ; // ***
}

DBconn* DB_connect( char* database )
{
    cdat ini =  connectiondata() ;
    // ...
}


And learn how to use C++ strings; look up std::string
http://www.mochima.com/tutorials/strings.html
Last edited on
JLBorges, yes, I have to clean this before, otherwise wouldn't be able to compile.
I was just trying to get another way to get it working like "vlad" recommends but that one I can't get to work.

Important parts:
1
2
3
4
5
6
7
8
9
10
11
12
//header
struct cdat connectiondata();

//function
struct cdat connectiondata()
{
    struct cdat ini;

    strcpy(ini.user, "thatsme");

//main
struct cdat ini = connectiondata();


That from main I can use out of functions, at top of program and then ini is reachable allaround, just what I search for...

But when we takling...
If I use "namespace std" (like for strings), include C++ headers like <string> and assign one string like mystring = "mytry" then I get compiled exe about 430 kb (under release). Same program, if I use C strings is about 9.5 kb (exe).

Is this normal or I messed something with compiler options?
> If I use "namespace std" (like for strings), include C++ headers like <string>
> and assign one string like mystring = "mytry"
> then I get compiled exe about 430 kb (under release).
> Same program, if I use C strings is about 9.5 kb (exe).
> Is this normal

It is normal for a C++ program to have a larger memory footprint. For instance, the standard C++ streams are instantiated in addition to the standard C streams, there are a few more allocators than malloc() and friends, the implementation of the C++ portion of the library may call C library functions anyway, and so on. How much more depends on the implementation.

What platform do you intend to run this code on? Where 430 kb would be deemed to be extravagant?
JLBorges,
I try this on windows and intend to try on linux also.
As unexperience in C++ I have to ask is this normal and common, nothing more.
What this brings in practice I will see later with advancing...

Thanks for help, informations and advices for all which try to help.
> I try this on windows and intend to try on linux also.

Then just ignore the difference in size - 400 kb is not something that one would give a second thought to on these platforms. Open Task Manager and check the memory usage of the programs that you regularly - the browser, IDE etc.

This program is tiny and 430 kb vs. 10 kb looks like a lot. For a somewhat bigger program, 5 MB vs. 5.5 MB wouldn't look all that different.
Last edited on
Finally catch what vlad was mean:

common.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef COMMON_H_
#define COMMON_H_

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

struct person
{
    std::string name;
    int age;
};

/* those variables WILL BE global */
extern struct person p;
extern std::string debugmode;

/* global functions */
int fillstruct();

#endif /* COMMON_H_*/


func.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "common.h"
using namespace std;

/* defining GLOBALS declared by extern */
struct person p;
std::string debugmode;
/* END GLOBALS */

int fillstruct()
{
    p.name = "marie";
    p.age = 20;

    debugmode = "yes";
    return EXIT_SUCCESS;
}


main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "common.h"
using namespace std;

int main(int argc, char *argv[])
{
    fillstruct();

    cout << p.name << " " << p.age << " " << debugmode << endl;

    debugmode = "no";
    p.name = "john";

    cout << p.name << " " << p.age << " " << debugmode << endl;

    return EXIT_SUCCESS;
}


Defining of globals can be in public area (NOT inside any function) of any file which includes common.h, but not in more than only one file!! That way structure p is accesible on all files which includes common.h.
Last edited on
Topic archived. No new replies allowed.