473,385 Members | 1,766 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Initialization of a const matrix implemented as pointer-to-pointer

Subject: Initialization of a const matrix implemented as pointer-to-pointer

Hello everyone.

I've got the following matrix definition in a source file

static const char **a;

I need it to be initialized as an array of strings, something like

static const char **a = {"Alpha", "Beta", Charlie"};

I know the number of strings and their maximum length, but I can't use a
stack-allocated matrix for compatibility reasons with another piece of
code, which simply defines a

char** strings

to which the matrix has to be assigned to.

I thought I could write a static const declaration for each string

static const str1[MAX_LENGTH] ="Alpha"

and then declare the matrix as

static const char* a[NUM_OF_STRINGS] = {str1,str2,...}

would it be correct?

thanks for your attention

AT

Sep 10 '08 #1
17 2704
Andrea Taverna (Tavs) wrote:
Subject: Initialization of a const matrix implemented as pointer-to-pointer

Hello everyone.

I've got the following matrix definition in a source file

static const char **a;

I need it to be initialized as an array of strings, something like

static const char **a = {"Alpha", "Beta", Charlie"};

I know the number of strings and their maximum length, but I can't use a
stack-allocated matrix for compatibility reasons with another piece of
code, which simply defines a

char** strings

to which the matrix has to be assigned to.

I thought I could write a static const declaration for each string

static const str1[MAX_LENGTH] ="Alpha"

and then declare the matrix as

static const char* a[NUM_OF_STRINGS] = {str1,str2,...}

would it be correct?

thanks for your attention
Looks OK to me.
You don't need NUM_OF_STRINGS.
And if you have the strings available to write
static const str1[MAX_LENGTH] ="Alpha";
then you don't need str1 either.

How about
static const char *a[] = {"Alpha", "Beta", Charlie"};
?

/* BEGIN new.c output */

Alpha
Beta
Charlie

/* END new.c output */

/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
static const char *a[] = {"Alpha", "Beta", "Charlie"};
size_t index;

puts("/* BEGIN new.c output */\n");
for (index = 0; index != sizeof a / sizeof *a; ++index) {
puts(a[index]);
}
puts("\n/* END new.c output */");
return 0;
}

/* END new.c */

--
pete
Sep 10 '08 #2
On Wed, 10 Sep 2008 13:57:47 +0200, "Andrea Taverna (Tavs)"
<a.****@libero.itwrote:
>Subject: Initialization of a const matrix implemented as pointer-to-pointer

Hello everyone.

I've got the following matrix definition in a source file

static const char **a;
In this case, sizeof a will probably be 4 or 8.
>
I need it to be initialized as an array of strings, something like

static const char **a = {"Alpha", "Beta", Charlie"};

I know the number of strings and their maximum length, but I can't use a
stack-allocated matrix for compatibility reasons with another piece of
code, which simply defines a

char** strings
>
to which the matrix has to be assigned to.
There should be no problem "assigning the array" to this pointer.
>
I thought I could write a static const declaration for each string

static const str1[MAX_LENGTH] ="Alpha"

and then declare the matrix as

static const char* a[NUM_OF_STRINGS] = {str1,str2,...}
If NUM_OF_STRINGS is 3 (to be consistent with your example), sizeof a
will probably be 12 or 24.
>
would it be correct?
It depends on how you plan to use a.

In the first example, is a true pointer. It can appear on the left
side of the assignment operator. In the second, a is an array which
cannot appear there. However, in both cases, a can appear on the
right of the assignment operator.

If all you want is a variable name that can be subscripted to evaluate
to different strings, then the second will work. If you delete the
"static", it will become a "stack allocated matrix" (technically an
automatic array of char*). When the array name "a" appears in an
expression context other than as the operand of sizeof and &, it will
be converted to the address of a[0] with type "pointer to type of
a[0]". Since a is an array of char*, a[0] is the first char* in the
array. The type "pointer to type of a[0]" is simply "pointer to
char*" also known as char**. Therefore you can assign the array name
"a" to the variable "strings" in the other code.

On the other hand, if you need a true pointer that can be reassigned
to point to different sets of strings, then something of the form:

const astr1[] = "Alpha";
...
const astrx[] = "Omega";
const bstr1[] = "Alef";
...
const bstrx[] = "Tav";
const char* A[] = {astr1,...,astrx};
const char* B[] = {bstr1,...,bstrx};
const char **a = A;
...
a = B;
and anywhere in your code you can say
strings = a;

--
Remove del for email
Sep 10 '08 #3
Barry Schwarz ha scritto:
In this case, sizeof a will probably be 4 or 8.
>I need it to be initialized as an array of strings, something like

static const char **a = {"Alpha", "Beta", Charlie"};

I know the number of strings and their maximum length, but I can't use a
stack-allocated matrix for compatibility reasons with another piece of
code, which simply defines a

char** strings
> to which the matrix has to be assigned to.

There should be no problem "assigning the array" to this pointer.
Actually there is. GCC warns that they're not compatible
On the other hand, if you need a true pointer that can be reassigned
to point to different sets of strings, then something of the form:

const astr1[] = "Alpha";
...
const astrx[] = "Omega";
const bstr1[] = "Alef";
...
const bstrx[] = "Tav";
const char* A[] = {astr1,...,astrx};
const char* B[] = {bstr1,...,bstrx};
const char **a = A;
...
a = B;
and anywhere in your code you can say
strings = a;
that's precisely what I'm going to do.

Thanks

AT
Sep 10 '08 #4
Ok, I've tried both ways, Barry's and Pete's. GCC still wars about
compatibility, but it behaves correctly at run time, so the problem is set.

Thank you :D

AT
Sep 10 '08 #5
Andrea Taverna (Tavs) wrote:
Barry Schwarz ha scritto:
In this case, sizeof a will probably be 4 or 8.
I need it to be initialized as an array of strings, something like

static const char **a = {"Alpha", "Beta", Charlie"};

I know the number of strings and their maximum length, but I can't use a
stack-allocated matrix for compatibility reasons with another piece of
code, which simply defines a

char** strings
to which the matrix has to be assigned to.
There should be no problem "assigning the array" to this pointer.

Actually there is. GCC warns that they're not compatible
That's because the second declaration should be

const char** strings;

If you don't have the power to change the declaration of 'strings',
check the documentation of the other piece of code very carefully. Is
that code going to attempt to write to those strings? If not, then it
was a mistake on the designer's part to declare "strings" without
using const. However, it's a mistake you can deal with by simply use a
cast:

strings = (char**)a;

However, it if will be writing to the strings, then this is not an
appropriate approach; the memory allocated for string literals is not
necessarily writable. In that case, follow the example given below,
but remove the word "const" wherever it appears:
On the other hand, if you need a true pointer that can be reassigned
to point to different sets of strings, then something of the form:

const astr1[] = "Alpha";
...
const astrx[] = "Omega";
const bstr1[] = "Alef";
...
const bstrx[] = "Tav";
const char* A[] = {astr1,...,astrx};
const char* B[] = {bstr1,...,bstrx};
const char **a = A;
...
a = B;
and anywhere in your code you can say
strings = a;
Sep 10 '08 #6
"Andrea Taverna (Tavs)" <a.****@libero.itwrites:
Ok, I've tried both ways, Barry's and Pete's. GCC still wars about
compatibility, but it behaves correctly at run time, so the problem is
set.
Don't be satisfied with code that produces warnings. Understand why
the warning is being produced. Most of the time, you should fix the
code so the warning goes away (note: adding a cast is rarely the right
fix). In some cases, it makes sense to leave the code as it is and
accept the warning, but most warnings indicate a real problem in the
code, one that's likely to bite you later on.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Sep 10 '08 #7
On Wed, 10 Sep 2008 16:16:23 +0200, "Andrea Taverna (Tavs)"
<a.****@libero.itwrote:
>Barry Schwarz ha scritto:
>In this case, sizeof a will probably be 4 or 8.
>>I need it to be initialized as an array of strings, something like

static const char **a = {"Alpha", "Beta", Charlie"};

I know the number of strings and their maximum length, but I can't use a
stack-allocated matrix for compatibility reasons with another piece of
code, which simply defines a

char** strings
>> to which the matrix has to be assigned to.

There should be no problem "assigning the array" to this pointer.

Actually there is. GCC warns that they're not compatible
I would be nice if you told us what the warning said. It is probably
a complaint about loss of "const" so remove that qualifier from your
code.
>
>On the other hand, if you need a true pointer that can be reassigned
to point to different sets of strings, then something of the form:

const astr1[] = "Alpha";
...
const astrx[] = "Omega";
const bstr1[] = "Alef";
...
const bstrx[] = "Tav";
const char* A[] = {astr1,...,astrx};
const char* B[] = {bstr1,...,bstrx};
const char **a = A;
...
a = B;
and anywhere in your code you can say
strings = a;

that's precisely what I'm going to do.
You will still have the const problem.

--
Remove del for email
Sep 11 '08 #8
>I would be nice if you told us what the warning said. It is probably
>a complaint about loss of "const" so remove that qualifier from your
code.
Sure.
I don't have the code at hand. More or less it says:
"Warning: assignment between incompatible types"

We fixed it by adjusting the declaration of the 'strings' field.
Now they're both declared as const char**, and the problem would be solved.
However I had to change the C standard from gnu89 (gcc's default) to
c99, and with the following piece of code

const char * a [] =
{
"alpha", "beta","charlie"
};

const struct my_structure my_s = (const struct my_structure)
{
.x = 10;
.strings = a; // <- Error
};

and the latter standard it complains with the following message:
"Error: initializer element is not constant"
With gnu89 it compiles fine.
Sep 19 '08 #9
On Fri, 19 Sep 2008 19:43:53 +0200, "Andrea Taverna (Tavs)"
<a.****@libero.itwrote:
I would be nice if you told us what the warning said. It is probably
a complaint about loss of "const" so remove that qualifier from your
code.
Sure.
I don't have the code at hand. More or less it says:
"Warning: assignment between incompatible types"

We fixed it by adjusting the declaration of the 'strings' field.
Now they're both declared as const char**, and the problem would be solved.
However I had to change the C standard from gnu89 (gcc's default) to
c99, and with the following piece of code

const char * a [] =
{
"alpha", "beta","charlie"
};

const struct my_structure my_s = (const struct my_structure)
{
.x = 10;
.strings = a; // <- Error
};

and the latter standard it complains with the following message:
"Error: initializer element is not constant"
With gnu89 it compiles fine.
If this code is outside of a function then my_s has static duration.
Initialization of a static object must be a compile time constant
since it occurs before any code is executed. The same restriction
applies to compound literals outside of a function body (6.5.2.5-3).

I can't help with gnu89 except to suggest that you specify the
appropriate options to prohibit extensions.

--
Remove del for email
Sep 20 '08 #10
Barry Schwarz wrote:
If this code is outside of a function then my_s has static duration.
Initialization of a static object must be a compile time constant
since it occurs before any code is executed. The same restriction
applies to compound literals outside of a function body (6.5.2.5-3).
Uh, yes. I forgot to specify that the initialization takes place in the
global scope (in a source file).

Ehm, could I ask you how I should change the code to have the error
fixed? I couldn't figure it out.
thanks

Andrea
Sep 22 '08 #11
On Mon, 22 Sep 2008 13:59:22 +0200, "Andrea Taverna (Tavs)"
<a.****@libero.itwrote:
>Uh, yes. I forgot to specify that the initialization takes place in the
global scope (in a source file).

Ehm, could I ask you how I should change the code to have the error
fixed? I couldn't figure it out.
To answer your question:

If you can limit yourself to C99 systems, you might be able to
use a compound literal.

Otherwise, I think you need to cheat. Create an
initialization function which you will call early in main. In this
function, access the const structures using non-const pointers and
initialize everything. Mark the structures volatile so the compiler
doesn't optimize away any accesses thinking it knows what values are
in the structures.

The real question is why are the structures at file scope. If the
answer is that they are used so frequently that you cannot afford to
pass them (or their addresses) to all the different functions that
need them then rethink how you access them. If you define the
structures in main, you can create global pointers to const, assign
values to the pointers in main, and have all the other functions
access the structures through the pointers. Since the structures are
no longer static, you have more flexibility in how you initialize
them.

--
Remove del for email
Sep 23 '08 #12
"Andrea Taverna (Tavs)" <a.****@libero.itwrites:
Barry Schwarz ha scritto:
>To answer your question:

If you can limit yourself to C99 systems, you might be able to
use a compound literal.

If you mean this:
my_s {
Did you have "my_s = {"? What you have posted look like a syntax error.
.x = 10,
.strings = {"alpha","beta","gamma"}
}
No, a compound literal would look like this:

.strings = (const char *[]){"alpha","beta","gamma"}

(again, this is C99).

--
Ben.
Sep 23 '08 #13
Ben Bacarisse ha scritto:
>
Did you have "my_s = {"? What you have posted look like a syntax error.
Oh, yes, I meant

const struct my_structure my_s = (const struct my_structure)
{
.x = 10;
.strings = {"alpha","beta","gamma"}
};

No, a compound literal would look like this:

.strings = (const char *[]){"alpha","beta","gamma"}
Gotcha. now it accept the assignment, but there's still that error:
initializer element is not constant

Andrea
Sep 23 '08 #14
"Andrea Taverna (Tavs)" <a.****@libero.itwrites:
Ben Bacarisse ha scritto:
<snip>
>No, a compound literal would look like this:

.strings = (const char *[]){"alpha","beta","gamma"}

Gotcha. now it accept the assignment, but there's still that error:
initializer element is not constant
You'd better post a small example that shows the problem. On my
system the above compiles silently. (BTW, that line is not,
technically, an assignment -- it is part of an initialisation.)

--
Ben.
Sep 24 '08 #15
Ben Bacarisse ha scritto:
You'd better post a small example that shows the problem. On my
system the above compiles silently.
struct my_structure
{
int x;
const char ** strings;
};

const struct my_structure my_s = (const struct my_structure)
{
.x = 10,
.strings = (const char *[]){"alpha","beta","charlie"}
}; // <-error

The compiler (gcc4.3.0-8 for Red Hat) says the error is on the last line
(BTW, that line is not,
technically, an assignment -- it is part of an initialisation.)
Gotcha

thanks

Andrea
Sep 24 '08 #16
"Andrea Taverna (Tavs)" <a.****@libero.itwrites:
Ben Bacarisse ha scritto:
>You'd better post a small example that shows the problem. On my
system the above compiles silently.

struct my_structure
{
int x;
const char ** strings;
};

const struct my_structure my_s = (const struct my_structure)
Just leave out this "top-level" compound literal.
{
.x = 10,
.strings = (const char *[]){"alpha","beta","charlie"}
}; // <-error
I.e. write:

const struct my_structure my_s = {
.x = 10,
.strings = (const char *[]){"alpha","beta","charlie"}
};

--
Ben.
Sep 24 '08 #17
Now it WORKS! thank you!

Andrea
Sep 24 '08 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
by: JKop | last post by:
Is this them all?: class Dummy { public: Dummy() {} Dummy(const Dummy& original) { }
9
by: Steven T. Hatton | last post by:
The following works: template <typename T> struct ID3M{ static const T ID; }; template <typename T> const T ID3M<T>::ID = {{1,0,0},{0,1,0},{0,0,1}};
2
by: Matthias Kaeppler | last post by:
Hi, say I have an arbitrary class Bar: 1 Bar a; 2 Bar b(a); 3 Bar c = a; In line 3, is the default ctor called for c _first_ and _then_ the assignment operator, or is c never default...
4
by: Javi | last post by:
Hello there!. I would like to create a class with an array as attribute. This array is the same for all the objects so I'd like to declare it as static, but the problem is: where and how should I...
4
by: Stephen Mayes | last post by:
I have initialized an array like this. const char matrix = { {0, 1, 2, 3}, {0, 1, 2}, {0, 1} }; gcc, (with no options set,) errors unless I specify
4
by: Marcus Kwok | last post by:
I found a bug in VC++ .NET 2003 regarding default initialization of arrays of primitives in a constructor initialization list, as detailed in this post:...
15
by: luke.yolanda | last post by:
hi everyone I have a question. First, I have implemented a huge matrix in a program, like 'unsigned char matrix;', when I executed this program, the error occured. Then I modified the ...
2
by: WinniePooh | last post by:
Hi there, I've the following code (here a snippet). ///////////////////////////////// // *.h file ///////////////////////////////// class ParameterTypeNames { public: static const...
23
by: Jess | last post by:
Hello, I understand the default-initialization happens if we don't initialize an object explicitly. I think for an object of a class type, the value is determined by the constructor, and for...
2
by: subramanian100in | last post by:
Consider the following program: #include <iostream> using namespace std; class Base { public: Base(int x = 0);
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.