Re: [ROOT] TObjString confusion

From: George Heintzelman (georgeh@sparrowhawk.chm.bnl.gov)
Date: Mon Aug 07 2000 - 23:11:22 MEST


> Any explanations why this won't work:
> 
> {
>   gROOT->Reset();
>   TObjString *Avars[23] = { "Total", "Debrems", "Dedelta", "Deelse", 
> 			   "Deepair", "Demunu", "Demuon", "Costhmu", 
> 			   "Deelse", "Ener", "Gmtns", "Gmtsec", "Id",
> 			   "Ievent", "Nch", "Nhits", "Nstr", "Ntr", 
> 			   "Phimu", "Toff","Trigg", "Vmu", "Zmu" };

Avars is an array of pointers to ObjString. If you try to compile this, 
it won't work, because you cannot initialize a pointer to an Objstring 
with a pointer to const char (which is what quoted strings are). In 
CINT, it appears to have been accepted but not in a meaningful way; 
what you get is an array of pointers to char which CINT thinks is an 
array of pointers to TObjString, leading to segvios if you try to treat 
them as pointers to TObjString. Here's a simpler example so you can see 
what CINT is really doing when you perform this statement:

root [0] TString *arr[2]={"A","B"}
root [1] arr[0]
(class TString*)0x8649a10
root [2] arr[0].Data()

 *** Break *** segmentation violation
Root > x = (char *)(arr[0])
Warning: Automatic variable x allocated in global scope 
FILE:/tmp/fileizWw2Z_cint LINE:1
(char* 0x8649a10)"A"
root [4] char *y = (char *)(arr[1])
root [5] y
(char* 0x8649a30)"B"

You can initialize a TObjString with a pointer to constant char, 
though. Assuming you are compiling, you should be able to do this (note 
that specifying the size is optional in C++, unless of course you need 
to know the size elsewhere):

TObjString Avars[] = {"Blah", "Blah", ...}

Apparently CINT does not know this syntax, which is legitimate C++ code:
root [0] TString arr[2]={"A","B"}
Error: Illegal initialization of arr[2]. Constructor exists  
FILE:/tmp/fileKy2phQ_cint LINE:1

Masa, could you comment? This compiles cleanly under gcc-2.91.66, and 
probably ought to work in CINT:
#include "TString.h"

int main() {
  TString arr[2]={"A","B"};
}

Anyway, since this doesn't seem to work in CINT, I'm not sure my 
comments will be too helpful, but maybe... The best way to do what you 
really want in CINT is probably something like this, but it's not at 
all elegant:

const Char_t *vars[23] = { "Blah", "Blah", "Blah" ... };
TObjString Avars[23];
for (int i = 0; i<23; i++) {
	Avars[i] = vars[i];
}


>   TString temp = Avars[0].GetString();

Avars[0] is a pointer to an ObjString. If you are compiling, you would 
get an error here for using '.' when you meant '->'. CINT probably will 
let you do this, though.

>   cout << temp.Data() << endl;
> }

This brings up another question: Could the root guys please provide:

ostream & operator<<(ostream &os, const TString &str) {
  return os << str.Data();
}

in TString.h? You really oughtn't to have to write temp.Data() in order 
to do this.

George Heintzelman
gah@bnl.gov



This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:31 MET