开发者

Setting static const char[] to a predefined static const char[] fails

开发者 https://www.devze.com 2022-12-11 16:16 出处:网络
Hey guys! When I try to do the following in a header file static const char FOOT[] = \"Foot\"; static const char FEET[] = FOOT;

Hey guys! When I try to do the following in a header file

static const char FOOT[] = "Foot";
static const char FEET[] = FOOT;

I get a compiler error of error: initializer fails to determine size of FEET. I wa开发者_JAVA百科s wondering what the cause of this is, and if there is a way to rectify it. Thanks!


Even though why you get this error has been answered, there's more to the story. If you really need for FEET to be an array, then you can make it a reference instead of a pointer:

char const foot[] = "foot";

char const (&feet)[sizeof foot] = foot;
// reference to array (length 5) of constant char
// (read the declarations "from the inside-out")

char const* const smelly_feet = foot;
// constant pointer to const char

int main() {
  cout << sizeof feet << ' ' << feet << '\n';
  cout << sizeof smelly_feet << ' ' << smelly_feet << '\n';
  cout << sizeof(void*) << " - compare to the above size\n";
  return 0;
}

(More examples of the inside-out rule.)

Secondly, static at file and namespace scope means internal linkage; so when you use it in a header, you'll get duplicate objects in every TU using that header. There are cases when you want this, but I see no reason for it in your code, and it's a common error.

Regarding array size: The sizeof operator returns the memory-size of an object or instance of a type. For arrays this means the total memory-size of all of its items. Since C++ guarantees that sizeof(char) is 1, the memory-size of a char array is the same as its length. For other array types, you can divide by the memory-size of one item to get the length of an array:

void f() {
  int array[5];
  assert((sizeof array / sizeof *array) == 5);
}

And you can generalize it to a function template:

template<class T, int N>
int len(T (&)[N]) {
  return N;
}
// use std::size_t instead of int if you prefer

This exists in boost as boost::size.

You may see code that uses sizeof array / sizeof *array, either through a macro or directly, either because it's old or doesn't want to complicate matters.


The cause is that you are saying that FEET[] is an array of chars but you're initializing it to a ptr; To rectify, you can change FEET from FEET[] to *FEET Could also do the same with FOOT


There is no '=' operator for arrays in C++, you need to use strcpy or something similar (which you can't do with a static const). Depending on your requirements the following might be useful:

#define contentsOfFoot "FOOT"
static const char FOOT[5] = contentsOfFoot;
static const char FEET[5] = contentsOfFoot;
static const char *feeet = FOOT;


static is deprecated, and const variables at namespace scope are effectively static, anyway. Also, please reserve ALL_CAPS for preprocessor identifiers.

A bigger question is why you are using raw arrays at all. You very likely want something more like this:

std::string const foot = "foot";
std::string const feet = foot;

Or, more likely:

#include <string>

namespace spbots {

    typedef std::string string_t;

    string_t const foot = "foot";
    string_t const feet = foot;
}


One way would be this

static const char FOOT[] = "Foot";
static const char *FEET = FOOT;


I want to emphasise that you shouldn't put that stuff in a header file. Variables should only be put in header files if you want to make them globally visible (generally not a great idea but it's a legitimate technique).

feet.h
extern char feet[];

feet.cpp
char feet[] = "FEET";

Now when you include feet.h in a different .cpp file, say leg.cpp, the declaration in feet.h means leg.cpp can see and use the array defined in feet.cpp

The extern keyword has the opposite meaning to the static keyword you use. A typical use of static is as follows;

feet.cpp
static char feet[] = "FEET";

Now feet[] is explicitly not visible outside feet.cpp. The static keyword is responsible for this lack of visibility. So static=local, extern=global and (perhaps unfortunately?) extern is the default, so if you don't use either keyword you get extern whether you like it or not.

Because static=local, there's nothing to communicate to other modules, so no need to have a declaration in a header file for other modules to see. Everything is kept within feet.cpp, probably a better idea than a global variable.

Another point I am implicitly trying to get through with this explanation is that declarations go into header files, definitions go into .cpp files. In your question you have a definition in a header file. Not illegal, but if you include it in more than one file (and if you don't, why would you put it in a header?), you will get a single variable defined multiple times, which will give you a link error.

All of this is actually old school C rather than C++ in the modern sense of the word. In other words you are really writing C, but since C is (almost) a subset of C++, you can still use C++ to do this stuff.

0

精彩评论

暂无评论...
验证码 换一张
取 消