LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Can I predefine constant array in c? (https://www.linuxquestions.org/questions/programming-9/can-i-predefine-constant-array-in-c-823350/)

kalleanka 08-01-2010 04:48 AM

Can I predefine constant array in c?
 
Can I predefine constant array in c?

with constants i do
#define NAMEOFCONST value

is it possible to do this for an array? And if not I would like to know why. I suspect it has to do with memory handeling and pointers.

Sergei Steshenko 08-01-2010 05:35 AM

Quote:

Originally Posted by kalleanka (Post 4051539)
Can I predefine constant array in c?

with constants i do
#define NAMEOFCONST value

is it possible to do this for an array? And if not I would like to know why. I suspect it has to do with memory handeling and pointers.

"C" has 'const' keyword which applies to arrays too.

http://en.wikipedia.org/wiki/Const-correctness

jf.argentino 08-01-2010 03:36 PM

To instantiate array values at declaration time use
Code:

int A[] = { 0, 1, 2, 3 };
or
Code:

int B[5] = { 0 };
to initialize all five values with zero (at least with gcc >= 4.x.)

kalleanka 08-12-2010 12:46 PM

hmmm

I have a global.h for constants and it works great for #define and typdefs. With the arrays i get compile warnings or linking error.

With:
int A[] = { 0, 1, 2, 3 };
I get linkin error since it will be defined several times.

With:
static int A[] = { 0, 1, 2, 3 };
i get compilation warning 'defined but not used' in a lot of places.

The thing is that they are used but in another .c file.

I guess i have to turn of this function in gcc since its hard to se other warnings. But i would really like to predefine these arrays.

dugan 08-12-2010 12:54 PM

Quote:

Originally Posted by kalleanka (Post 4064382)
I get linkin error since it will be defined several times.

You're not using include guards?

BTW, I'm quite sure that declaring variables in include files is not consistent with best practises.

johnsfine 08-12-2010 01:21 PM

Quote:

Originally Posted by kalleanka (Post 4064382)
I have a global.h for constants and it works great for #define and typdefs. With the arrays i get compile warnings or linking error.

I don't know any decent solution. I think there is no decent solution.

Sometimes I use a very ugly kludge to get the most important aspect of the solution, which is the ability to define the array once within an include file that is included into multiple .c files. But that means the syntax must be ugly for use of the array.

In the include file:
Code:

inline int const* a()
{
    static int const a_static[] = { 13, 17, 39 };
    return a_static;
}

In each .c file, where you would have used a[n], you must instead use a()[n]

Quote:

Originally Posted by dugan (Post 4064390)
You're not using include guards?

Include guards don't help this issue at all. The problem is not including the .h file multiple times in one compilation unit (which include guards would fix). The problem is including it into multiple compilation units, so it is multiply defined at link time.

Quote:

BTW, I'm quite sure that declaring variables in include files is not consistent with best practises.
Actually, declaring variables in include files generally is considered to be best practice.

We're talking about defining variables in include files. Good software architecture often calls for defining variables (especially const variables) in the include file where those variables are declared. But C and C++ provide no good way to define variables in include files (I think that is a flaw in both languages). So best practice in C is generally to go along with that language flaw by declaring variables in include files but defining them in .c files.

PTrenholme 08-12-2010 01:24 PM

You might want to consider the enum data type.

johnsfine 08-12-2010 01:37 PM

Quote:

Originally Posted by PTrenholme (Post 4064432)
You might want to consider the enum data type.

Quote:

Originally Posted by kalleanka (Post 4051539)
Can I predefine constant array in c?

PTrenholme, were you answering that question? It appears not.

Quote:

Originally Posted by kalleanka (Post 4051539)
with constants i do
#define NAMEOFCONST value

Maybe PTrenholme was answering that non question. I also want to answer that non question.

#define in C and C++ is an ugly feature. Because it doesn't respect scope, its use quickly becomes a landmine in large projects. You should not use #define for ordinary integer constants because there is a better alternative.

As PTrenholme may be suggesting, enum is a better substitute (compared to #define) for the things you'd like to be able to do with const int but the language doesn't let you.

Sergei Steshenko 08-12-2010 01:43 PM

Quote:

Originally Posted by johnsfine (Post 4064441)
...
#define in C and C++ is an ugly feature. Because it doesn't respect scope, its use quickly becomes a landmine in large projects.
...

No, the problem is management/managers.

There is not much conceptual difference between

#define SCOPE_PREFIX____ACTUAL_MACRO_NAME MACRO_BODY

and

SomeClass::SomeName

, but the former (SCOPE_PREFIX) should be mandated by project management. I.e. properly managed project first establishes naming convention - especially for global things. Class names are global too.

johnsfine 08-12-2010 01:51 PM

Quote:

Originally Posted by Sergei Steshenko (Post 4064445)
No, the problem is management/managers.

I apologize for answering the non question. You demonstrated one of the problems with answering non questions. I disagree with you about this whole scoping and project management issue. But I don't want to debate that in this thread (I expect it would be pointless to debate that anywhere).

My answer to the actual question of this thread is way back in post #6

kalleanka 08-12-2010 02:41 PM

thanks for all the anwsers.

I want all the constants in one place.


im using include guards so its not that.

johnsfine thats an intressting solution. And I agree that const declarations in includefiles are a flaw in c and c++.

enumerations would work for int but not for strings.

I think i shall encapsulate it in functions and call functions for the constants. Then its not a big step to use a settingfile for the constants if i need it in the future. I do want all the constants i one place. Its polltimes, messeges(diffrent languages), spacings, colors, layouts etc for a kiosk (wm, desktop, coinmech, servercommunication etc).

thanks to you all

I will sleep in it and use johnsfines solution or make functions in a .c file.

PTrenholme 08-12-2010 06:15 PM

Quote:

Originally Posted by kalleanka (Post 4064487)
. . .
enumerations would work for int but not for strings.
. . .

John's solution seems fine. ;)

But if enum would do except for strings, consider this:
Code:

$ cat enum.c
#include <stdio.h>
enum str {
str1,
str2,
str3};
char *String[]={"First string", "Second one", "Third"};
int main()
{
    printf("%s\n", String[str1]);
    printf("%s\n", String[str2]);
    printf("%s\n", String[str3]);
}

It's a two-step definition, but it seem quite straightforward.

kalleanka 08-13-2010 04:09 AM

PTrenholme that will still give the warnings 'defined but not used'.


what i will do is to encapulat it in global.c

static int A[] = { 0, 1, 2, 3 };

int get_A(int i)
{
return A[i];
}


and in global.h

int get_A(int i);


this makes it really easy to understand for programmers in the future.


Thanks for all the anwsers.

johnsfine 08-13-2010 05:27 AM

If you're willing to have the normal (for C and C++) split between a .h file and a .c file, then you could do all this the usual way, without the wrapper function.

In global.h

extern int A[];

In global.c

int A[] = { 0, 1, 2, 3};

In other .c files include global.h and use A[n]

I thought you had some reason to want the definition to be in the include file.

If you really prefer hiding the array reference in an access function, that is also OK. But do you care about performance? The method I gave to hide the reference can be mostly elided by the optimizer, so it has minimal impact on performance compared to the ordinary method (declare in .h, define .c and directly use in other .c). Your method cannot be elided by the optimizer, so it has a significant performance cost.

When intentionally hiding a data reference in a function, I generally put that function in an include file so it can be optimized out. For very best performance, you may need to put the actual data definition in a .c file (with an extern declaration in the .h). My trick of burying the data as a function static inside the access function might confuse the optimizer enough that it is only partially elided.

kalleanka 08-13-2010 07:19 AM

Quote:

Originally Posted by johnsfine (Post 4065028)

In global.h

extern int A[];

In global.c

int A[] = { 0, 1, 2, 3};

In other .c files include global.h and use A[n]

This is of course the best way. That i did not think about that. And performance might be a problem but i do not know for now. I have the hole system (100M) running in ram (1000M) and its for a kiosk with intel atom.

Thanks a lot. I really appreciate it.

ps I never took a course in c or c++ but i know java, pascal, lisp. C got more issues(memory, pointer, strings etc) for a programmer and i seem to fall into the trap all the time.


All times are GMT -5. The time now is 09:37 AM.