21

This is a newbie C/Objective-C question :-)

Let say I want a CGRectOne and a CGRectTwo constants.

How can I declare that?

Thanks, Jérémy

justin
  • 104,054
  • 14
  • 179
  • 226
jchatard
  • 1,881
  • 2
  • 20
  • 25

4 Answers4

51

The other answers are fine -in some cases-.

A) declaring it static will emit a copy per translation. That is fine if it is visible to exactly one translation (i.e. its definition is in your .m/.c file). Otherwise, you end up with copies in every translation which includes/imports the header with the static definition. This can result in an inflated binary, as well as an increase to your build times.

B) const CGRect CGRectOne = {...}; will emit a symbol in the scope it is declared. if that happens to be a header visible to multiple translations you'll end up with link errors (because CGRectOne is defined multiple times -- e.g. once per .c/.m file which directly or indirectly includes the header where the constant is defined).

Now that you know the context to use those 2 declarations in, let cover the extern way. The extern way allows you to:

  • declare the constant in a header
  • use the constant in many translations
  • while emitting exactly one definition of the constant

The extern approach is ideal for reusing the constant among multiple files. Here's an example:

File.h

// the declaration in the header:
extern const CGRect CGRectOne;

File.c/m

// the definition:

#import "File.h"

const CGRect CGRectOne = { { 0.0f, 0.0f }, { 1.0f, 1.0f } };

Note: Omitting the const would just make it a global variable.

justin
  • 104,054
  • 14
  • 179
  • 226
  • note: technically, you have more options with c++ - i answered as though the question was c/objc. – justin Jan 14 '11 at 11:06
  • 1
    This helped me out greatly. Good answer. – samfu_1 Mar 27 '11 at 03:49
  • I tried to declare like `extern const CGRect SCREENBOUNDS;` in .h file.. But it is saying `Type name does not allow storage class to be specified`.. you help me to understand this error? – Praveen Apr 09 '14 at 07:15
  • @Praveen first guess: you have tried to declare the constant inside an `@interface` (or other scope). the extern constant should be declared in the same (global) scope as other extern C declarations (e.g. functions, constants). – justin Apr 25 '14 at 16:49
21

There are a couple of options. With C89,

const CGRect CGRectOne = { { 0.0f, 0.0f }, { 1.0f, 1.0f } };

With C99,

const CGRect CGRectOne = {
    .origin.x = 0.0f,
    .origin.y = 0.0f,
    .size.width = 1.0f,
    .size.height = 1.0f
};

or

const CGRect CGRectOne = {
    .origin = { .x = 0.0f, .y = 0.0f },
    .size   = { .width = 1.0f, .height = 1.0f }
};
6

Something like this

static CGRect CGRectOne = (CGRect){.origin.x = 1.0f, .origin.y = 1.0f, .size.width = 1.0f, .size.height = 1.0f};
Nyx0uf
  • 4,609
  • 1
  • 25
  • 26
0

The technique used here worked well for me: http://www.cocos2d-iphone.org/forum/topic/2612#post-16402

Essentially its the extern method described by Justin, but it provides a pretty full example.

Also, this answer on StackOverflow provides a good example too: Constants in Objective-C

Community
  • 1
  • 1
Nick
  • 2,803
  • 1
  • 39
  • 59