warning C4267 and warning C4996

B

B. Williams

I am receiving two warnings in my code and can't figure out why. Will
someone look at this and tell me what I have done wrong?

#include <iostream>

using std::cout;

#include <string>

using std::string;

class PPG{

public:

PPG(char *a, char b, int c)

{ dresscolor =b;

power = c;

setname(a);}//end constructor 1

PPG()

{ setname("Ms. Bellum");

dresscolor ='p';

power = 0;

}//end default constructor

char * getname()const {return name;}


void setname(char *a){

int l =strlen(a);

name = new char[l+1];

strcpy(name,a);

name[l] = '\0';

}//end setname

int getpower() const{return power;}

void setpower(int z){power = z;}

char getdresscolor() const{return dresscolor;}

void setdresscolor(char v){dresscolor=v;}

void print() const

{ cout <<name << " likes to wear ";

switch (dresscolor){

case 'g': case 'G':

cout <<"green dresses. She uses her "; break;

case 'b':case 'B':

cout <<"blue dresses. She uses her ";break;

case 'p': case 'P':

cout <<"pink dresses. She uses her ";

}//end switch

if (power == 1)

cout << "ice breath to defeat her enemies.\n";

else if (power ==2)

cout << "ability to talk to squirrels to confuse evil villians.\n";

else if (power ==3)

cout <<"bad attitude to stop evil doers.\n";

else

cout <<"girl power to rule the world.\n";

}//end print

bool operator==(PPG &ppg)

{ return (strcmp(name, ppg.name)==0); }

private:

char * name;

char dresscolor; //g-reen, b-lue, p-pink

int power; //1-ice breath, 2- squirrel speak, 3-bad attitude

}; //end class

#include "ppg.h"

#include <iostream>

int main()

{

PPG girl1("Bubbles", 'b', 2);

girl1.print();

PPG badgirl("Princess",'g', 4);

badgirl.print();


return 0;

}//end main

These are the warnings I am getting.

warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible
loss of data

warning C4996: 'strcpy' was declared deprecated

I am also getting this.

program files\microsoft visual studio 8\vc\include\string.h(73) : see
declaration of 'strcpy'
 
V

Victor Bazarov

B. Williams said:
I am receiving two warnings in my code and can't figure out why. Will
someone look at this and tell me what I have done wrong?

Nothing, really. These are just warnings.
[...]

These are the warnings I am getting.

warning C4267: 'initializing' : conversion from 'size_t' to 'int',
possible loss of data

warning C4996: 'strcpy' was declared deprecated

I am also getting this.

program files\microsoft visual studio 8\vc\include\string.h(73) : see
declaration of 'strcpy'

Stop using C strings and start using 'std::string'.

V
 
M

mlimber

B. Williams said:
I am receiving two warnings in my code and can't figure out why. Will
someone look at this and tell me what I have done wrong?

#include <iostream>

using std::cout;

#include <string>

using std::string;

class PPG{

public:

PPG(char *a, char b, int c)

{ dresscolor =b;

power = c;

setname(a);}//end constructor 1

PPG()

{ setname("Ms. Bellum");

dresscolor ='p';

power = 0;

}//end default constructor

char * getname()const {return name;}


void setname(char *a){

int l =strlen(a);

name = new char[l+1];

strcpy(name,a);

name[l] = '\0';

}//end setname

int getpower() const{return power;}

void setpower(int z){power = z;}

char getdresscolor() const{return dresscolor;}

void setdresscolor(char v){dresscolor=v;}

void print() const

{ cout <<name << " likes to wear ";

switch (dresscolor){

case 'g': case 'G':

cout <<"green dresses. She uses her "; break;

case 'b':case 'B':

cout <<"blue dresses. She uses her ";break;

case 'p': case 'P':

cout <<"pink dresses. She uses her ";

}//end switch

if (power == 1)

cout << "ice breath to defeat her enemies.\n";

else if (power ==2)

cout << "ability to talk to squirrels to confuse evil villians.\n";

else if (power ==3)

cout <<"bad attitude to stop evil doers.\n";

else

cout <<"girl power to rule the world.\n";

}//end print

bool operator==(PPG &ppg)

{ return (strcmp(name, ppg.name)==0); }

private:

char * name;

char dresscolor; //g-reen, b-lue, p-pink

int power; //1-ice breath, 2- squirrel speak, 3-bad attitude

}; //end class

#include "ppg.h"

#include <iostream>

int main()

{

PPG girl1("Bubbles", 'b', 2);

girl1.print();

PPG badgirl("Princess",'g', 4);

badgirl.print();


return 0;

}//end main

These are the warnings I am getting.

warning C4267: 'initializing' : conversion from 'size_t' to 'int', possible
loss of data

warning C4996: 'strcpy' was declared deprecated

I am also getting this.

program files\microsoft visual studio 8\vc\include\string.h(73) : see
declaration of 'strcpy'

It is customary to note which line(s) generate the warnings or errors.
I'd also suggest you start indenting your code (your editor can
probably even do it for you -- look under Edit | Advanced, or something
like that in Visual Studio). It makes it MUCH easier to read.

As for the warnings, I'd guess that you're seeing the first when you
assign the result of strlen(), which returns size_t (see
http://www.cppreference.com/stdstring/strlen.html) to an int. The
former type is unsigned, while the latter is signed. You risk losing
the correct length by mixing signed and unsigned types. Change the
variable type to size_t.

The second warning just indicates that strcpy() has been deprecated
because it is unsafe. Use strncpy if you must. Better all around would
be to drop character arrays and C-style string functions altogether in
favor of std::string. That's the C++ way (see
http://www.parashift.com/c++-faq-lite/containers.html#faq-34.1), and it
will handle many of the trickier details for you.

If you must use strcpy (e.g., if your professor or boss requires it for
some inane reason), use a #pragma to disable that message.

Cheers! --M
 
M

Michael

FYI, Visual Studio's help function is useful in deciphering these
compiler error messages.

Just do Help->Search, and type C4267 into the box, or C4996, or
whatever. You'll get a nice page about what the error is, how to fix
it, etc.

Michael
 
P

Pete Becker

mlimber said:
The second warning just indicates that strcpy() has been deprecated
because it is unsafe.

Well, deprecated by Microsoft because some folks at Microsoft think it's
unsafe. Neither the C standard nor the C++ standard has deprecated it,
and there are no plans to do so.

There's nothing wrong with the way strcpy is used in your code. On the
other hand, using the name l for a variable is not so good, because it's
easily confused with 1.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
F

Frederick Gotham

B. Williams posted:
warning C4267: 'initializing' : conversion from 'size_t' to 'int',
possible loss of data


If you _really_ want to convert a size_t to an int, then a cast should
suppress such a warning:

int i = (int)strlen(p);

warning C4996: 'strcpy' was declared deprecated


By whom. . . ? "strcpy" is an efficient algorithm and you can presume it
works perfectly on every implementation.
 
P

Pete Becker

Pete said:
Well, deprecated by Microsoft because some folks at Microsoft think it's
unsafe. Neither the C standard nor the C++ standard has deprecated it,
and there are no plans to do so.

There's nothing wrong with the way strcpy is used in your code. On the
other hand, using the name l for a variable is not so good, because it's
easily confused with 1.

Whoops, sorry about the misattribution. That last paragraph was meant
for the original poster.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
R

red floyd

Frederick said:
B. Williams posted:



If you _really_ want to convert a size_t to an int, then a cast should
suppress such a warning:

int i = (int)strlen(p);




By whom. . . ? "strcpy" is an efficient algorithm and you can presume it
works perfectly on every implementation.

By Microsoft, [SARCASM] in their infinite wisdom [/SARCASM].
 
B

BobR

Frederick Gotham wrote in message ...
B. Williams posted:

If you _really_ want to convert a size_t to an int, then a cast should
suppress such a warning:

int i = (int)strlen(p);

'C' casting? In this NG?

int i = int( strlen(p) );

or use a 'C++' cast.
int len = static_cast<int>( strlen(a) );

or, like elsethread:
size_t len = strlen( a );
// std::size_t len = strlen( a );

Do the "duh!"
int len( 0 );
if( size_t( strlen(a) ) <
static_cast<size_t>(
std::numeric_limits<int>::max() ) ){
len = static_cast<int>( strlen(a) );
}


<G>
 
B

Bill Medland

red said:
Frederick said:
B. Williams posted:



If you _really_ want to convert a size_t to an int, then a cast should
suppress such a warning:

int i = (int)strlen(p);




By whom. . . ? "strcpy" is an efficient algorithm and you can presume it
works perfectly on every implementation.

By Microsoft, [SARCASM] in their infinite wisdom [/SARCASM].
Yeh; and how many people are going to follow thjeir advice and use strncpy
and forget it doesn't guarantee to terminate the string.
 
R

robertwessel2

Bill said:
By whom. . . ? "strcpy" is an efficient algorithm and you can presume it
works perfectly on every implementation.

By Microsoft, [SARCASM] in their infinite wisdom [/SARCASM].
Yeh; and how many people are going to follow thjeir advice and use strncpy
and forget it doesn't guarantee to terminate the string.


Ignoring the issue of whether or not MS depreciating functions like
this is a good thing (in MS's defense, these are functions that have
historically lead to numerous vulnerabilities, this is only a warning
- the functions remain available and behave exactly as expected, and
it's an easy warning to turn off)... At the very least, I think MS
should have avoided the term depreciated.

Actually MS has depreciated strncpy() as well. They recommend (their
new, and obviously non-standard) strcpy_s(), which does deal with the
trailing null as you'd typically expect.
 
T

tragomaskhalos

unsafe. Neither the C standard nor the C++ standard has deprecated it,
and there are no plans to do so.

Indeed. To the OP, you can put a #pragma in your project's stdafx.h
file (assuming you are using one) to disable the strcpy warning as it
really is just a Microsoftism (just because _they_ can't use strcpy
safely doesn't mean you can't :)) . The size_t <> int one, whilst
annoying, does make sense. The trouble is that using int for loop
indices is an extremely common idiom; you can either use a pragma to
shut that warning up as well, or you can rewrite your loops to use
size_t / collection<...>::size_type instead of int. I'd recommend the
latter, but opinion seems to be divided.
 
F

Frederick Gotham

BobR:

'C' casting? In this NG?


Indeed.

int i = int( strlen(p) );


I like how you took a "C cast" as you call it, and disguised it as the
initialisation of a nameless object, very misleading. Try this:

double a = 5.6;

double *p = &a;

int i = int(p);

Why do you prefer your misleading disguised cast to the more recognisible
canonical cast?

or use a 'C++' cast.
int len = static_cast<int>( strlen(a) );


I'd consider that, but it's just too long-winded for my taste.
 
P

Pete Becker

Frederick said:
BobR:




I like how you took a "C cast" as you call it, and disguised it as the
initialisation of a nameless object, very misleading.

Not really. The language definition calls this a function-style cast.

--

-- Pete

Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." For more information about this book, see
www.petebecker.com/tr1book.
 
D

Diego Martins

Bill said:
By whom. . . ? "strcpy" is an efficient algorithm and you can presume it
works perfectly on every implementation.


By Microsoft, [SARCASM] in their infinite wisdom [/SARCASM].
Yeh; and how many people are going to follow thjeir advice and use strncpy
and forget it doesn't guarantee to terminate the string.


Ignoring the issue of whether or not MS depreciating functions like
this is a good thing (in MS's defense, these are functions that have
historically lead to numerous vulnerabilities, this is only a warning
- the functions remain available and behave exactly as expected, and
it's an easy warning to turn off)... At the very least, I think MS
should have avoided the term depreciated.

Actually MS has depreciated strncpy() as well. They recommend (their
new, and obviously non-standard) strcpy_s(), which does deal with the
trailing null as you'd typically expect.

Microsoft states std::copy algorithm is deprecated too.

I am sure I'd go postal if I was a M$ employee
 
B

BobR

Frederick Gotham wrote in message ...
BobR:

I like how you took a "C cast" as you call it, and disguised it as the
initialisation of a nameless object, very misleading. Try this:

double a = 5.6;
double *p = &a;
int i = int(p);

Why do you prefer your misleading disguised cast to the more recognisible
canonical cast?

{
double a = 5.6;
double *p = &a;

int i = int(p);
int ia = int(*p);

std::cout <<" double a="<<a<< std::endl;
std::cout <<" int i = int(p)="<<i<< std::endl;
std::cout <<" int ia = int(*p)="<<ia<< std::endl;
}
/* -- output --
double a=5.600000
int i = int(p)=10611788 // <-- address (in decimal)(maybe truncated)
int ia = int(*p)=5 // <-- value p was 'pointing to'
*/

Works fine for me. Sure, some care must be taken, but, is the 'C' cast any
safer? (I find them much less safe in some cases. (to-from 'void*').
I'd consider that, but it's just too long-winded for my taste.

But, I think that is the point. It stands out like a sore thumb. It says,
"HEY, are you really positive you *need* to cast this?". And
'reinterpret_cast<>' is even more typing, saying, "danger, please double
check your design, and what you are casting from-to.".

I'm not trying to argue or piss you off (I value your opinion/knowledge).
Might be some newbie lurkers reading here that should have the choice.
 
F

Frederick Gotham

BobR:
{
double a = 5.6;
double *p = &a;

int i = int(p);
int ia = int(*p);

std::cout <<" double a="<<a<< std::endl;
std::cout <<" int i = int(p)="<<i<< std::endl;
std::cout <<" int ia = int(*p)="<<ia<< std::endl;
}
/* -- output --
double a=5.600000
int i = int(p)=10611788 // <-- address (in decimal)(maybe truncated)
int ia = int(*p)=5 // <-- value p was 'pointing to'
*/

Works fine for me. Sure, some care must be taken, but, is the 'C' cast any
safer? (I find them much less safe in some cases. (to-from 'void*').


My intent was to demonstrate that they're exactly equivalent. The following
two statements are exactly equivalent regardless of the types used:

Type1 obj1 = (Type1)obj2;

Type1 obj1 = Type1(obj2);

Just because you've switched around some parentheses, doesn't make it any
"safer". The first one looks like a cast, so I use it when I want a cast.
The second looks like the initialisation of a nameless object, so I use it
when I want a nameless object.

But, I think that is the point. It stands out like a sore thumb. It says,
"HEY, are you really positive you *need* to cast this?". And
'reinterpret_cast<>' is even more typing, saying, "danger, please double
check your design, and what you are casting from-to.".


I don't share your caution. I use casts quite a lot to achieve what I want;
if there was something wrong with them, I wouldn't use them. The following
is perfectly okay for me:

int i = 5;
short a = (short)i; /* Cast to suppress warning */

I only resort to the more verbose casts when the cast in question is more
complex than simply converting one kind of intrinsic to another.

I'm not trying to argue or piss you off (I value your opinion/knowledge).
Might be some newbie lurkers reading here that should have the choice.


No bother.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top