?
Solved

Question on use of new char(len)

Posted on 2011-10-05
20
Medium Priority
?
558 Views
Last Modified: 2012-05-12
I found the following in a code review and flagged it as incorrect ... even though I was told it compiled with no errors.

   size_t len = Value->Length;
   char * pValue = new char(len);

Does anyone else think this is incorrect?

C++ Visual Studio 2005 running on Windows XP SP2 box.

Thanks for your input.
0
Comment
Question by:SLCleary
20 Comments
 
LVL 9

Expert Comment

by:bz43
ID: 36921584
Hi, You might want to add this to another zone besides only Windows XP Operating System.  Something in programming.  You are allowed up to three zones with each question.  Of course, you can add more but it might cost extra; I'm not sure.
0
 
LVL 31

Assisted Solution

by:Zoppo
Zoppo earned 124 total points
ID: 36922707
Hi SLCleary,

the new-syntax to allocate an array is 'new <type> [size]', so the second line should be
char * pValue = new char[len];

Open in new window

Hope that helps,

ZOPPO
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36922810
to add to above:

you normally would allocate len+1 characters in order to be able to add a terminating zero char.

Sara
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 35

Expert Comment

by:sarabande
ID: 36922841
i don't know what type the 'Value' variable is. if it is std::string* the length function needs to have a small letter at begin.

generally, it is rarely a good reason to have pointers to string objects. better use strings and not string pointers cause all modern string classes have internal reference counting what makes them actually to smart pointers (self-managing pointers).

Sara
0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 124 total points
ID: 36923340
>> Does anyone else think this is incorrect?
It depends.

char * pValue = new char(len);

Open in new window


will create 1 char in the heap and initialise it with whatever value is in len. This may or may not be what was intended. We can't really say whether it is right or wrong (although, it is probably not what was intended).

*scratching head*

What's wrong with using std::string?
http://www.cplusplus.com/reference/string/string/
0
 
LVL 35

Assisted Solution

by:sarabande
sarabande earned 252 total points
ID: 36923403
i dare to say it is not intended and therefore wrong cause the vc compiler would throw warning C4267 when it should initialize a char by a size_t.

Sara

0
 
LVL 40

Expert Comment

by:evilrix
ID: 36923951
I am not convinced because that should just been seen as a constructor cast and, thus, it wouldn't issue a warning. Did you try it?
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36923973
yes.

the questioner uses visual studio 2005 where the compiler complains that the size_t argument might get truncated when casted to a char.

Sara
0
 
LVL 35

Accepted Solution

by:
sarabande earned 252 total points
ID: 36924020
of course, that isn't a strong evidence but we additional have that a length value in a new statement rarely is an initializer and that the new variable has the name pValue what not only would be a poor name for a char pointer pointing to a single byte with a length value but actually would be a misleading name which alone would needed to be blamed in a code review.

Sara
0
 
LVL 40

Expert Comment

by:evilrix
ID: 36924583
>> the questioner uses visual studio 2005 where the compiler complains that the size_t argument might get truncated when casted to a char.
That's odd, cos I just tried it on VS2005 and it definitely doesn't warn. Neither does it on gcc. I wouldn't expect it to, either.

>> of course, that isn't a strong evidence
No, and I'm not suggesting it is -- I'm just pointing out that as the code stands it is not incorrect. The asker asked, "Does anyone else think this is incorrect?" and my answer is no (because it's not in the sense of it is well formed code). That doesn't mean it was what was intended but it is most certainly not incorrect.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 36924586
>>  the compiler complains that the size_t argument might get truncated when casted to a char.
But, isn't the point of a cast to tell the compiler -- no need to warn me I really meant this?
0
 

Author Closing Comment

by:SLCleary
ID: 36924587
Thanks for the input.  I think the intent was to use [ ] and not ().
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36925287
evilrix, where do you see a cast?

i get the same warning when i do

size_t s = 1;
char c = s;

vc always warned when assigning (or initialising) from a type that had a different range.

it doesn't warn when i do an explicit cast:

size_t s = 1;
char c = (char)s;

Sara
0
 
LVL 40

Expert Comment

by:evilrix
ID: 36927575
>> it doesn't warn when i do an explicit cast
These two are semantically identical.

size_t s = 1;
char c = (char)s;

size_t s = 1;
char c = char(s);

Open in new window


>> evilrix, where do you see a cast?

This is performing a cast: char * pValue = new char(len);

Let me put it another way, semantically this...

char c = char(len); // len is a size_t

is the same as

char c = (char)len; // len is a size_t

...which is why C++ introduces the 'explicit' keyword (to stop a constructor performing a cast/implicit type conversion).

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=15

The explicit Keyword

The problem here is that the implicit conversion (taking place behind the programmer's back) switches off the compiler's static type checking. Without this implicit conversion, the compiler would have complained about a type mismatch. C++ creators perceived this problem long ago. They decided to add a "patch" to the language in the form of the keyword explicit. Constructors declared explicit will refuse to perform such implicit conversions:

http://www.cplusplus.com/doc/tutorial/typecasting/

Explicit conversion
C++ is a strong-typed language. Many conversions, specially those that imply a different interpretation of the value, require an explicit conversion. We have already seen two notations for explicit type conversion: functional and c-like casting:

short a=2000;
int b;
b = (int) a;    // c-like cast notation
b = int (a);    // functional notation 

Open in new window


>> vc always warned when assigning (or initialising) from a type that had a different range.
Except that code is not just assigning, it is also casting.

>> it doesn't warn when i do an explicit cast
Bingo! An that is exactly what that code is doing.

I've now tested this with 2 compilers (GCC and V2005) and neither of them warn. I could test this with 100 standards compliant compilers -- none of them should warn because that is a perfectly well formed line of code (even if it wasn't what was intended).
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36939280
i tried the statements

size_t s = 17;
char * pc = new char(s);

Open in new window


with vs2008 and got

1>d:\projects\testconsole\main.cpp(14) : warning C4244: 'initializing' : conversion from 'size_t' to 'char', possible loss of data

i didn't try it with vs2005 cause i don't have a running system with vs2005 currently available. but i worked 4 years with vs2005 and i don't believe it has a different behavior regarding that than vs2003 or vs2008. i well remember that any simple assignment witd string::size or string::find at the right side required a cast when the left side was an int.

so, i think vs2005 will behave identically,

i also am not convinced that the new char(s) actually is a cast. i think the (s) is an initializer and the char(s) works like a default copy constructor for the char type. then the size_t must be truncated to a char and the compiler complains.

i tested that theory with

char * pc = new char(char(s));

Open in new window


and it gives no warning.

Sara
0
 
LVL 40

Expert Comment

by:evilrix
ID: 36939341
>> with vs2008 and got warning C4244: 'initializing' : conversion from 'size_t' to 'char', possible loss of data
I get no warning with your example code in either 2005, 2008 or 2010 nor various versions of gcc, as expected.

Your warning refers to line 14 -- can you post the exact code you compiled please?

>> i also am not convinced that the new char(s) actually is a cast
You don't have to be convinced -- doesn't change the fact that it is exactly what it is.

Quoted from the C++03 standard...

A simple-type-specifier followed by a parenthesized expression-list constructs a value of the specified
type given the expression list. If the expression list is a single expression, the type conversion expression
is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4).

5.4 Explicit type conversion (cast notation) [expr.cast]
1 The result of the expression (T) cast-expression is of type T. The result is an lvalue if T is a reference
type, otherwise the result is an rvalue. [Note: if T is a non-class type that is cv-qualified, the cv-qualifiers
are ignored when determining the type of the resulting rvalue; see 3.10. ]

...and just in case that isn't clear...

http://www.cprogramming.com/tutorial/lesson11.html

C++ supports two other types. First is the function-style cast:
 
int main()       
{
  cout<< char ( 65 ) <<"\n"; 
  cin.get();
}

Open in new window


This is more like a function call than a cast as the type to be cast to is like the name of the function and the value to be cast is like the argument to the function. Next is the named cast, of which there are four:
 
int main()       
{
  cout<< static_cast<char> ( 65 ) <<"\n"; 
  cin.get();
}

Open in new window


static_cast is similar in function to the other casts described above, but the name makes it easier to spot and less tempting to use since it tends to be ugly. Typecasting should be avoided whenever possible. The other three types of named casts are const_cast, reinterpret_cast, and dynamic_cast. They are of no use to us at this time.

Or how about...

http://www.cplusplus.com/doc/tutorial/typecasting/

Explicit conversion
C++ is a strong-typed language. Many conversions, specially those that imply a different interpretation of the value, require an explicit conversion. We have already seen two notations for explicit type conversion: functional and c-like casting:

short a=2000;
int b;
b = (int) a;    // c-like cast notation
b = int (a);    // functional notation 

Open in new window



Are you still not convinced? If not I give up.

0
 
LVL 35

Expert Comment

by:sarabande
ID: 36941671
i get the warning when i add the the two lines

size_t s = 17;
char * pc = new char(s);

Open in new window


to the begin of an arbitrary main function of a win32 console program and compile that source (above the main function are only #include statements).

i tried VC6, VC7.1 (VS2003), and VC9 (VS2008) all at warning level 3 (default).

in the warning they use the wording 'initializing', what in my opinion - sorry for still not being convinced and even have an own and different 'opinion' on the subject (you may take it as 'senile stubborness') - indicates they create (construct) one single char and use the value given in the parantheses for initializing purpose. that also would mean the 'char' belongs to the 'new' where a type is mandatory and doesn't have a secondary cast functionality.

the part of the C03 standard you posted doesn't contradict that cause we don't have a single expression 'char(s)' but 'new char(s)'.  

Sara
0
 
LVL 40

Expert Comment

by:evilrix
ID: 36941772
Just out of interested, are you creating a brand new project using vanilla settings? In each case and on each compiler I tested this on that is what I did and in no case did I get a warning.

>> we don't have a single expression 'char(s)' but 'new char(s)'
The only difference is that the former's result is allocate on the stack and the latters on the heap. Semantically, they are both performing a constructor style functional cast. In both cases the cast is performed via the types constructor.

Maybe this link does a better job of explaining?
http://www.glenmccl.com/bett_014.htm

>> sorry for still not being convinced

Heh. That's fine. I've quoted the appropriate part of the C++ standard that covers this. You can draw your own conclusions from what that states. If nothing else, at least you now understand why I stated it was a cast, which was really the only thing that I wanted to clarify.

I, just to be clear (for the askers sake if nothing else), that this is the reason the code isn't technically incorrect and that it is this behaviour that is the reason there is an explicit keyword that allows one to declare a constructor as being explicit. Without that keyword the constructor (silently -- except, apparently your compilers) performs an explicit type conversion.
0
 
LVL 35

Expert Comment

by:sarabande
ID: 36943297
the project is a console project i use for ee code to test. it has nothing but default settings beside of the character set which is ANSI and not UTF-16.

the link you posted doesn't has a en

a search for "constructor style functional cast" and "new" doesn't give a hit.

i changed to "constructor style cast" and "c++" and "new" and got 341 hits. a few peeks into the results don't seem to support your thesis that the expression right of new is a cast. i actually didn't find one single new statement with a primitive type there. the "new" in the result pages always was unrelated to the cast samples.

if i use a class type with new i can pass any combination of arguments supported by any of the constructors. so with new AClass(arg1[, ...]) we definitively have no cast when the argument types fit to one of the constructors. a cast can come to play if the argument types are different and for some types there can be an implicit cast on the argument possible. but that is not the 'constructor style cast'.

Sara

 



0
 
LVL 40

Expert Comment

by:evilrix
ID: 36947159
Right, I've managed to create the warning. The only time I can get it is when I enable the check for 64 bit portability (this is a Microsoft extension and has nothing to do with ANSI C++). Disable it and the warning should go away.

http://msdn.microsoft.com/en-us/library/yt4xw8fh.aspx

I have no idea why Microsoft are warning when 64 bit portability is enabled (since this *is* a cast) but it's not like Microsoft aren't known for warning about things that are perfectly valid C++ (for example, deprecating standard posix functions that they have no right to claim are deprecated).

Sara, I'm sorry that you still don't believe me when I tell you that this is performing a constructor conversion/cast. The standard is pretty clear in my opinion and in all cases every compiler I've tried (with sensible settings) works as I would expect.

NB. I've tested this on VS2005, VS2008, VS2010, GCC4.5.3 and GCC3.2

At this point I'm going to end my participation here but I am going to start a new discussion topic so we can explore this further with the input of the other experts. Please do join in.

http://www.experts-exchange.com/Programming/Languages/CPP/Q_27390122.html
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Issue: Unstable cursor in Windows XP and Windows runs extremely slow in that any click will bring up the Hour glass (sometimes for several seconds before giving you what you want) . Troubleshooting Process and the FINAL FIX: This issue see…
Today, still in the boom of Apple, PC's and products, nearly 50% of the computer users use Windows as graphical operating systems. If you are among those users who love windows, but are grappling to keep the system's hard drive optimized, then you s…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
Suggested Courses

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question