A homework project I'm working on uses static and dynamic arrays. However, I'm not implementing the dynamic arrays yet and this is a weird discrepancy trying to get the length of my static arrays.
I used a series of开发者_运维技巧 cout statements to try and find out what was giving me a segmentation fault, since the process seemed straightforward. What I found was that in my driver, it was computeing a correct range and length, but once I passed the array into a user-defined class function, the same statements performed on the same array had different results.
My driver function:
using namespace std;
#include <iostream>
#include "/user/cse232/Projects/project07.string.h"
int main()
{
const char string1[] = {'a', 'b', 'c', 'd', 'e', 'f'};
String test1();
cout << "Size of array: " << sizeof(string1) << endl;
cout << "Size of item in array: " << sizeof(char) << endl;
cout << "Length of array: " << (sizeof(string1)/sizeof(char)) << endl;
cout << "Range of array" << (sizeof(string1)/sizeof(char))-1 << endl << endl;
String test2(string1);
}
When run, I get this output from the driver:
Size of array: 6
Size of item in array: 1
Length of array: 6
Range of array5
My support file:
/* Implementation file for type "String" */
using namespace std;
#include <iostream>
#include "/user/cse232/Projects/project07.string.h"
String::String( const char Input[] )
{
cout << "Size of array: " << sizeof(Input) << endl;
cout << "Size of item in array: " << sizeof(char) << endl;
cout << "Length of array: " << (sizeof(Input)/sizeof(char)) << endl;
cout << "Range of array" << (sizeof(Input)/sizeof(char))-1 << endl << endl;
/* Bunch of reallocation stuff that is commented out
for the time being, unimportant*/
}
String::~String()
{
Capacity = 0;
Length = 0;
Mem = NULL;
}
And here is the output I get from the support file,
Size of array: 4
Size of item in array: 1
Length of array: 4
Range of array3
which is obviously not right. If it helps, here is the header file (omitting unimplemented functions). It is unalterable:
/******************************************************************************
Project #7 -- Interface file for type "String"
******************************************************************************/
#ifndef STRING_
#define STRING_
using namespace std;
#include <iostream>
class String
{
private:
unsigned Capacity; // Number of memory locations reserved
unsigned Length; // Number of memory locations in use
char * Mem; // Pointer to memory to hold characters
public:
// Construct empty string
//
String()
{
Capacity = 0;
Length = 0;
Mem = NULL;
}
// Destroy string
//
~String();
// Construct string by copying existing string
//
String( const String& );
// Construct string by copying C-style character string
//
String( const char[] );
#endif
My biggest question is why I am getting two separate outputs. The first one is the one I need to use while allocating memory; otherwise I get a segmentation fault. Can anyone offer advice?
Your function is actually doing something you don't realize - it decays the array you pass into a pointer to the first element.
Basically your function signature: String::String( const char Input[] )
would be equivalent to the signature String::String(const char *input)
.
So when you do sizeof
, you're actually getting the size of an char *
, not of the array.
You cannot pass an array directly to the function and expect to be able to get the size of the array. If you must use raw arrays like this, you can alter your function so that you pass in the size of the array with it. If you can not modify the signature, then another thing you can do is put in a sentinel value (like \0
byte) and use a loop to count the size of the array.
edit
What I think you really want to learn about is C-style strings, rather than just using a character array that is not null-terminated. This does fit the model of what your assignment seems to want you to do, and allows you to avoid manipulating these immutable headers.
once you pass an array into a function the compiler no longer knows its size
the called function just sees
foo(char[])
It does not know how big it is, the array has become a pointer and when you ask for the size of a pointer you get 4 (on a 32 bit machine)
The in memory representation of an array does not contain its length. This is a well known and intractable problem, its why std::vector exists
Unfortunately you cannot pass arrays like this. When you have a function like this:
String::String( const char Input[] )
you are only passing in a pointer to the very first element. You will also need to pass the size of the array into the constructor.
Others have answered your question, so I'll just supplement it with a little idea - There is a way you can pass an array to a function without having it decay into a pointer.
const size_t SIZE = 6; //Or whatever other array size you want to pass.
String::String(const char (&Input)[SIZE])
{
//TODO
}
Since it's not easy to always count the size of your array, a better mechanism looks like this -
template<size_t N>
String::String(const char (&Input)[N])
{
//TODO
}
If you don't know what size_t
means, just assume that it is similar to int
for now, and you'll learn more about this eventually (either by teaching yourself, or in some textbook. Probably the former).
The somewhat weird looking parameter to the function -
const char (&Input)[SIZE]
means that you are passing
- A reference (denoted by &)
- It's called
Input
- It's a reference to an array made up of
const char
's (Note: If I had put the&
outside the parenthesis, like this:const char & Input[SIZE]
, then it would be treated as an array ofconst char&
's - thus the need to introduce parenthesis to make sure that the reference is to the array itself, not each element in th3e array) - The size of the array is
SIZE
, whereSIZE
has to be a constant.
If you are not sure what the template
line is all about, that's probably out of scope for this discussion :-)
All of this will only work for true arrays, for which the size is a constant value that can be computed at compile-time. Otherwise, it's not going to work, and you'll have to use a sentinel value (like '\0'
and dynamically compute the length of your 'array' by looping over the contents.
精彩评论