Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

bobber205

macrumors 68020
Original poster
Nov 15, 2005
2,182
1
Oregon
This is legal at school in Visual Studio.

Code:
  if (which >= 1 && which <= numEntries) {
                which = which -1;
                cout << "New First Name: ";
                cin >> temp;
                strcpy(firstnames[index[which]], temp);
                cout << endl;

                cout << "New Last Name: ";
                cin >> temp;
                strcpy(lastnames[index[which]], temp);
                cout << endl;

                cout << "New Phone Number: ";
                cin >> temp;
                strcpy(phonenumbers[index[which]], temp);
                cout << endl;

                cout << "New Birthday: ";
                cin >> temp;
                strcpy(birthdays[index[which]], temp);
                cout << endl;

                
            
}
            else cout << "INVALID Number." << endl;

But in Xcode I'm getting a

Code:
 invalid types 'char (*)[50][char* ()(const char*, int)]' for array subscript

Any ideas why? What function should I use?

What's a good reference for what C++ functions I can and can't use in Xcode's compiler?
 

MarkCollette

macrumors 68000
Mar 6, 2003
1,559
36
Toronto, Canada
1. Exactly what datatypes are: which, index, firstnames, lastnames, phonenumbers, birthdays?

2. What aren't you using structures or classes, instead of these parallel arrays?

3. Why are you using strcpy(), instead of strncpy()?

4. Why are you (I think) using char arrays, instead of string objects?
 

colocolo

macrumors 6502
Jan 17, 2002
480
132
Santiago, Chile
1. Exactly what datatypes are: which, index, firstnames, lastnames, phonenumbers, birthdays?

2. What aren't you using structures or classes, instead of these parallel arrays?

3. Why are you using strcpy(), instead of strncpy()?

4. Why are you (I think) using char arrays, instead of string objects?

Im guessing he's just just doing some basic data structure course in C at school, so he would be required to learn the basics of arrays first, before moving into structs. Clearly its not Objective-C or C++, so classes are out of the question :)
 

MarkCollette

macrumors 68000
Mar 6, 2003
1,559
36
Toronto, Canada
Im guessing he's just just doing some basic data structure course in C at school, so he would be required to learn the basics of arrays first, before moving into structs. Clearly its not Objective-C or C++, so classes are out of the question :)

Yeah, you're probably right. Except it is C++, since he's using cin and cout :)
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
3. Why are you using strcpy(), instead of strncpy()?

Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.
 

darkwing

macrumors 65816
Jan 6, 2004
1,210
0
Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.

This is a good point. I do rather wish that strncpy would return a pointer to the terminating \0 like stpcpy() does. It could return NULL if there isn't a terminating \0. I guess they wanted consistency with strcpy().
 

MarkCollette

macrumors 68000
Mar 6, 2003
1,559
36
Toronto, Canada
Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.

I didn't know that strncpy() padded with extra zeros if possible. But I do know that the simply workaround for potentially not adding the zero byte is to simply always have one extra slot at the end, and just put a '\0' in there, forcing termination.
 

savar

macrumors 68000
Jun 6, 2003
1,950
0
District of Columbia
Never, ever use strncpy. It doesn't do what you think it does.

When you copy into a buffer that is big enough, both strcpy and strncpy work fine. strcpy is better, because strncpy will _always_ fill the rest of the buffer with zeroes, which is painfully slow if you have a generously nice big buffer. If the buffer is not big enough, strcpy overwrites memory which will crash. strncpy doesn't overwrite memory, but it copies a string without the trailing '\0'. So if you try to use the result, _anything_ can happen. The result is, your program is likely to crash, but not where the bug is. Instead things will go wrong some time later.

Strange advice... most security experts would say exactly the opposite. Copying data without doing bounds checking is dangerous, especially if that data was supplied by a user. Your program might not crash; it might smash the stack and then execute harmful shell code.
 

MarkCollette

macrumors 68000
Mar 6, 2003
1,559
36
Toronto, Canada
Strange advice... most security experts would say exactly the opposite. Copying data without doing bounds checking is dangerous, especially if that data was supplied by a user. Your program might not crash; it might smash the stack and then execute harmful shell code.

I think the piont of that bad advice was that it's better for a situation to fail fast, at development time, then limp on into production.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
Strange advice... most security experts would say exactly the opposite. Copying data without doing bounds checking is dangerous, especially if that data was supplied by a user. Your program might not crash; it might smash the stack and then execute harmful shell code.

Security experts will tell you that strncpy lulls you into a false sense of security. You think you are secure but you are not. Now in reality you either make sure that the destination buffer is big enough before you call strcpy (in which case strncpy is pointless), or you write a function yourself that will do something sensible, unlike what strncpy does, if there is not enough space.

Lets say dst has space for ten chars. If you just call

strncpy (dst, src, 10);
len = strlen (dst);

strncpy won't overwrite anything, but len can be greater than 10, or the call to strlen can even crash, so strncpy doesn't gain anything. Any use of strncpy in some code makes me very, very worried.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
I think the piont of that bad advice was that it's better for a situation to fail fast, at development time, then limp on into production.

It can be worse.

Say you have a struct

typedef struct { char c [12]; int n; } mystruct;

and call strncpy (c, "this is a very very long string", 12);

On a PowerPC, the next byte in memory following the array c is the most significant byte of n. As long as 0 <= n <= 16000000 or so, the most significant byte of n is a zero, so there is a zero byte following the array c and c will behave as if it contained a valid string of 12 characters plus a trailing zero.

Compile your code for an Intel Macintosh. The next byte in memory following array c is now the least significant byte of n. If n has a value from 1 to 255, c doesn't behave like a string of 12 characters anymore. This is a great opportunity for a bug in your program that only happens in an Intel version, and is an absolute nightmare to find.

For example:

mystruct s;
strncpy (s.c, "This is a very very long string", sizeof (s.c));
for (s.n = 1; s.n <= 255; ++s.n)
if (strchr (s.c, s.n) != NULL)
printf ("s.c contains the character %c\n". s.n);

On a PowerPC, it will print that s.c contains the letters T, h, i, s, space, a, v and e. On an Intel Mac, it will print that s.c contains _all_ 255 letters which is strange because strlen (s.c) will return 12 after the loop is finished.
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
Security experts will tell you that strncpy lulls you into a false sense of security. You think you are secure but you are not. Now in reality you either make sure that the destination buffer is big enough before you call strcpy (in which case strncpy is pointless), or you write a function yourself that will do something sensible, unlike what strncpy does, if there is not enough space.

Lets say dst has space for ten chars. If you just call

strncpy (dst, src, 10);
len = strlen (dst);

strncpy won't overwrite anything, but len can be greater than 10, or the call to strlen can even crash, so strncpy doesn't gain anything. Any use of strncpy in some code makes me very, very worried.


strncpy isn't useless. Like szark said, you can use it to copy one string into a portion of another string, ie strncpy( dst, src, strlen( src ) )

In your above code if dst plays the role of a C string, ie is null terminated and is 10 characters long including the null character, then doing:-

strncpy( dst, src, 10 )

is a silly thing to do and it's the programmers fault and not strncpy() when the null character is overwritten.

b e n
 

MarkCollette

macrumors 68000
Mar 6, 2003
1,559
36
Toronto, Canada
It can be worse.

Say you have a struct

typedef struct { char c [12]; int n; } mystruct;

and call strncpy (c, "this is a very very long string", 12);

Not if you actually do what I said to do in this post.

Code:
typedef struct { char c [13]; int n; } mystruct; 

strncpy (mystruct.c, "this is a very very long string", 12);
mystruct.c[12] = '\0';
 

pilotError

macrumors 68020
Apr 12, 2006
2,237
4
Long Island
If your really worried about buffer overflows, and your string is null terminated, you can just use sizeof()

strncpy(mystruct.c, "this is a very very long string", sizeof(mystruct.c) - 1);

I though the GNU compilers deprecated a bunch of the original string copy functions and provided alternatives to avoid the whole buffer overflow thing.

I did a quick man check and didn't see them.

I also see a mac specific strlcpy in the man pages.
 

Catfish_Man

macrumors 68030
Sep 13, 2001
2,579
2
Portland, OR
Or we could just STOP USING C FOR GENERAL APPLICATION PROGRAMMING and save ourselves multiple huge classes of bugs, as well as speeding up development. It's a system programming language, folks. It's not suited for string processing. :mad:
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
If your really worried about buffer overflows, and your string is null terminated, you can just use sizeof()

strncpy(mystruct.c, "this is a very very long string", sizeof(mystruct.c) - 1);

You didn't think this through, did you?

If mystruct.c has n bytes, then the first n-1 bytes will be filled with data from the string, the last byte has its previous, probably unspecified value. So the behavior now depends on whatever was at that memory location earlier, which is generally unpredictable and may for example depend on which compiler optimisations you have turned on. This can give you another debugging nightmare: The possibility that a bug only turns up in a release version and doesn't happen in your debugging version.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
strncpy isn't useless. Like szark said, you can use it to copy one string into a portion of another string, ie strncpy( dst, src, strlen( src ) )

In your above code if dst plays the role of a C string, ie is null terminated and is 10 characters long including the null character, then doing:-

strncpy( dst, src, 10 )

is a silly thing to do and it's the programmers fault and not strncpy() when the null character is overwritten.

b e n

That was the point of my first post: Don't use strncpy. Yes, it is not its fault that it is ugly and useless, just don't use it.
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
You didn't think this through, did you?

If mystruct.c has n bytes, then the first n-1 bytes will be filled with data from the string, the last byte has its previous, probably unspecified value. So the behavior now depends on whatever was at that memory location earlier, which is generally unpredictable and may for example depend on which compiler optimisations you have turned on. This can give you another debugging nightmare: The possibility that a bug only turns up in a release version and doesn't happen in your debugging version.

I think the whole point was, that with mystruct.c[12] = '\0'; (as MarkCollete suggested) then strncpy(mystruct.c, "this is a very very long string", sizeof(mystruct.c) - 1); is fine.

Just my opinion but your examples for not using strncpy look like example of bad progamming technique/errors/bugs. You might as well say strcpy is a security problem because somebody might do this:-

Code:
char* fish = malloc( 20 ) ;
…
…
strcpy( fish, "a very long message that will spill over fish" ) ;

Anyway, not everybody uses strncpy to copy 'whole' C strings, and not all strings are null terminated.

b e n

EDIT: Also in some secure situations (though I admit I've never had to do this myself), it's important to overwrite the previous contents of strings so as not to leave keys etc in memory.
 

pilotError

macrumors 68020
Apr 12, 2006
2,237
4
Long Island
You didn't think this through, did you?

My point was if you wanted to avoid the buffer overflows, use the sizeof. I think he's capable of null terminating the string.

Then again, None of us should be programming in C, its a systems programming language you know! :p

Good quote from the Red Hat man pages:

BUGS
If the destination string of a strcpy() is not large enough (that is,
if the programmer was stupid/lazy, and failed to check the size before
copying) then anything might happen. Overflowing fixed length strings
is a favourite cracker technique.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.