Best c questions in September 2011

Once upon a time, when > was faster than < ... Wait, what?

95 votes

I am reading a wonderful OpenGL tutorial. It's unbelievably great, trust me. The topic I am currently at is Z-buffer. Aside from explaining what's it all about, the author mentions that we can perform custom depth tests, such as GL_LESS, GL_ALWAYS, etc. He also explains that the actual meaning of depth values (which is top and which isn't) can also be customized. I understand so far. And then the author says something unbelievable:

The range zNear can be greater than the range zFar; if it is, then the window-space values will be reversed, in terms of what constitutes closest or farthest from the viewer.

Earlier, it was said that the window-space Z value of 0 is closest and 1 is farthest. However, if our clip-space Z values were negated, the depth of 1 would be closest to the view and the depth of 0 would be farthest. Yet, if we flip the direction of the depth test (GL_LESS to GL_GREATER, etc), we get the exact same result. So it's really just a convention. Indeed, flipping the sign of Z and the depth test was once a vital performance optimization for many games.

If I understand correctly, performance-wise, flipping the sign of Z and the depth test is nothing but changing a < comparison to a > comparison. So, if I understand correctly and the author isn't lying or making things up, then changing < to > used to be a vital optimization for many games.

Is the author making things up, am I misunderstanding something, or is it indeed the case that once < was slower (vitally, as the author says) than >?

Thanks for clarifying this quite curious matter!

Disclaimer: I am fully aware that algorithm complexity is the primary source for optimizations. Furthermore, I suspect that nowadays it definitely wouldn't make any difference and I am not asking this to optimize anything. I am just extremely, painfully, maybe prohibitively curious.

If I understand correctly, performance-wise, flipping the sign of Z and the depth test is nothing but changing a < comparison to a > comparison. So, if I understand correctly and the author isn't lying or making things up, then changing < to > used to be a vital optimization for many games.

I didn't explain that particularly well, because it wasn't important. I just felt it was an interesting bit of trivia to add. I didn't intend to go over the algorithm specifically.

However, context is key. I never said that a < comparison was faster than a > comparison. Remember: we're talking about graphics hardware depth tests, not your CPU. Not operator<.

What I was referring to was a specific old optimization where one frame you would use GL_LESS with a range of [0, 0.5]. Next frame, you render with GL_GREATER with a range of [1.0, 0.5]. You go back and forth, literally "flipping the sign of Z and the depth test" every frame.

This loses one bit of depth precision, but you didn't have to clear the depth buffer, which once upon a time was a rather slow operation. Since depth clearing is not only free these days but actually faster than this technique, people don't do it anymore.

Why does a C comment like /* */ need '<'?

41 votes

My teams C-code guidelines write that it'd be better to place a '<' in a comment like shown below:

#define MAX_PACK_ITEM_NUM 50  /**<  max number of item */

I wonder, what is the real use of this '<' ?

It's a way for doxygen to generate documentation for members of a file/struct/union/class/enum. By using that marker, you can put comments after each member, leading to less clutter. You can read more about it here.

Does dynamic memory allocation differ in C and C++ in popular implementations?

39 votes

As far as the respective language standards go, C offers dynamic memory allocation only through the malloc() family, while in C++ the most common form of allocation is performed by ::operator new(). The C-style malloc is also available in C++, and many "baby's first allocator" examples use it as its core allocation function, but I am curious how contemporary compilers implement the actual production operator-new.

Is it just a thin wrapper around malloc(), or is it implemented fundamentally differently on account of the rather different memory allocation behaviour of a typical C++ program compared to a typical C program?

[Edit: I believe the main difference is usually described as follows: A C program has fewer, larger, long-lived allocations, while a C++ program has many, small, short-lived allocations. Feel free to chime in if that's mistaken, but it sounds like one would benefit from taking this into account.]

For a compiler like GCC it would be easy to just have one single core allocation implementation and use that for all relevant languages, so I wonder if there are differences in the details that try to optimize the resulting allocation performance in each language.


Update: Thanks for all the great answers! It looks like in GCC this is completely solved by ptmalloc, and that MSVC also uses malloc at the core. Does anyone know how the MSVC-malloc is implemented?

Here is the implementation used by g++ 4.6.1:

_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) throw (std::bad_alloc)
{
  void *p;

  /* malloc (0) is unpredictable; avoid it.  */
  if (sz == 0)
    sz = 1;
  p = (void *) malloc (sz);
  while (p == 0)
    {
      new_handler handler = __new_handler;
      if (! handler)
#ifdef __EXCEPTIONS
        throw bad_alloc();
#else
        std::abort();
#endif
      handler ();
      p = (void *) malloc (sz);
    }

  return p;
}

This is found in libstdc++-v3/libsupc++/new_op.cc inside the g++ source distro.

As you can see, it's a fairly thin wrapper around malloc.

edit On many systems it is possible to fine-tune the behaviour of malloc, typically by calling mallopt or setting environment variables. Here is one article discussing some features available on Linux.

According to Wikipedia, glibc versions 2.3+ use a modified version of the allocator called ptmalloc, which itself is a derivative of dlmalloc designed by Doug Lea. Interestingly, in an article about dlmalloc Doug Lea gives the following perspective (emphasis mine):

I wrote the first version of the allocator after writing some C++ programs that almost exclusively relied on allocating dynamic memory. I found that they ran much more slowly and/or with much more total memory consumption than I expected them to. This was due to characteristics of the memory allocators on the systems I was running on (mainly the then-current versions of SunOs and BSD ). To counter this, at first I wrote a number of special-purpose allocators in C++, normally by overloading operator new for various classes. Some of these are described in a paper on C++ allocation techniques that was adapted into the 1989 C++ Report article Some storage allocation techniques for container classes.

However, I soon realized that building a special allocator for each new class that tended to be dynamically allocated and heavily used was not a good strategy when building kinds of general-purpose programming support classes I was writing at the time. (From 1986 to 1991, I was the the primary author of libg++ , the GNU C++ library.) A broader solution was needed -- to write an allocator that was good enough under normal C++ and C loads so that programmers would not be tempted to write special-purpose allocators except under very special conditions.

This article presents a description of some of the main design goals, algorithms, and implementation considerations for this allocator.

How to count characters in a unicode string in C

34 votes

Lets say I have a string:

char theString[] = "你们好āa";

Given that my encoding is utf-8, this string is 12 bytes long (the three hanzi characters are three bytes each, the latin character with the macron is two bytes, and the 'a' is one byte:

strlen(theString) == 12

How can I count the number of characters? How can i do the equivalent of subscripting so that:

theString[3] == "好"

How can I slice, and cat such strings?

You only count the characters that have the top two bits are not set to 10 (i.e., everything less that 0x80 or greater than 0xbf).

That's because all the characters with the top two bits set to 10 are UTF-8 continuation bytes.

See here for a description of the encoding and how strlen can work on a UTF-8 string.

For slicing and dicing UTF-8 strings, you basically have to follow the same rules. Any byte starting with a 0 bit or a 11 sequence is the start of a UTF-8 code point, all others are continuation characters.

Your best bet, if you don't want to use a third-party library, is to simply provide functions along the lines of:

utf8left (char *destbuff, char *srcbuff, size_t sz);
utf8mid  (char *destbuff, char *srcbuff, size_t pos, size_t sz);
utf8rest (char *destbuff, char *srcbuff, size_t pos;

to get, respectively:

  • the left sz UTF-8 bytes of a string.
  • the sz UTF-8 bytes of a string, starting at pos.
  • the rest of the UTF-8 bytes of a string, starting at pos.

This will be a decent building block to be able to manipulate the strings sufficiently for your purposes.

How does C code call assembly code (e.g. optimized strlen)?

28 votes

I always read things about how certain functions within the C programming language are optimized by being written in assembly. Let me apologize if that sentence sounds a little misguided.

So, I'll put it clearly: How is it that when you call some functions like strlen on UNIX/C systems, the actual function you're calling is written in assembly? Can you write assembly right into C programs somehow or is it an external call situation? Is it part of the C standard to be able to do this, or is it an operating system specific thing?

The C standard dictates what each library function must do rather than how it is implemented.

Almost all known implementations of C are compiled into machine language. It is up to the implementers of the C compiler/library how they choose to implement functions like strlen. They could choose to implement it in C and compile it to an object, or they could choose to write it in assembly and assemble it to an object. Or they could implement it some other way. It doesn't matter so long as you get the right effect and result when you call strlen.

Now, as it happens, many C toolsets do allow you to write inline assembly, but that is absolutely not part of the standard. Any such facilties have to be included as extensions to the C standard.

Using WinRT from C?

27 votes

Watching the //BUILD stuff, I saw that WinRT API's can be consumed by C code:

enter image description here

I am rather excited about a fresh C API available to Win32 developers.

Where can I find information on the C WinRT API? How is it better than the existing Win32 C API?

WinRT is fundamentally COM, so using WinRT components from C is like using COM components from C. Like before, you get .idl files for all WinRT components, and also .h files produced from those .idl files. The .h files include both C++ and C declarations (wrapped in #ifdef __cplusplus as needed). You can just #include them and start hacking away.

It's not exactly neat, though, e.g. something like this C++/CX:

Windows::UI::Xaml::Controls::TextBlock^ tb = ...;
tb->Text = "Foo";

which is equivalent to this vanilla C++:

Windows::UI::Xaml::Controls::ITextBlock* tb = ...;
HSTRING hs;
hr = WindowsStringCreate(L"Foo", 3, &hs);
// check hr for errors
HRESULT hr = tb->set_Text(hs);
// check hr for errors
tb->Release();

would be written in C as:

__x_Windows_CUI_CXaml_CControls_CITextBlock* tb = ...;
HRESULT hr;
HSTRING hs;
hr = WindowsStringCreate(L"Foo", 3, &hs);
// check hr for errors
hr = __x_Windows_CUI_CXaml_CControls_CITextBlock_put_Text(tb, hs);
// check hr for errors
IUnknown_Release(tb);

Look inside "C:\Program Files (x86)\Windows Kits\8.0\Include\winrt" in Developer Preview to see the .idl and .h files.

segfault : interview question/C puzzle

27 votes

I came across the following C puzzle:

Q: Why does the following program segfault on IA-64, but work fine on IA-32?

  int main()
  {
      int* p;
      p = (int*)malloc(sizeof(int));
      *p = 10;
      return 0;
  }

I know that the size of int on a 64 bit machine may not be the same as the size of a pointer (int could be 32 bits and pointer could be 64 bits). But I am not sure how this relates to the above program. Any ideas?

The cast to int* masks the fact that without the proper #include the return type of malloc is assumed to be int. IA-64 happens to have sizeof(int) < sizeof(int*) which makes this problem obvious.

The comp.lang.c FAQ has an entry discussing why casting the return from malloc is never needed and potentially bad.

What does =+ mean in C?

23 votes

I came across =+ as opposed to the standard += today in some C code; I'm not quite sure what's going on here. I also couldn't find it in the documentation.

In ancient versions of C, =+ was equivalent to +=. Remnants of it have been found alongside the earliest dinosaur bones. Any more, it has no special meaning -- it's just a = followed by a +.

What does the operation c=a+++b mean?

22 votes

Possible Duplicate:
How is the expression x---y parsed? Is it a legal expression?

The following code has me confused

int a=2,b=5,c;
c=a+++b;
printf("%d,%d,%d",a,b,c);

I expected the output to be 3,5,8, mainly because a++ means 2 +1 which equals 3, and 3 + 5 equals 8, so I expected 3,5,8. It turns out that the result is 3,5,7. Can someone explain why this is the case?

It's parsed as c = a++ + b, and a++ means post-increment, i.e. increment after taking the value of a to compute a + b == 2 + 5.

Please, never write code like this.

Why is ~size_t(0) (== 0xFFFFFFFF in most 32-bit systems) not a valid array index?

19 votes

Quoting from this blogpost:

http://www.codesynthesis.com/~boris/blog/2008/10/13/writing-64-bit-safe-code/

This works because a valid memory index can only be in the [0, ~size_t(0)-1] range. The same approach, for example, is used in std::string.

So why is ~size_t(0) (this should usually equal 0xFFFFFFFF in 32-bit systems) not a valid array index? I assume that if you have 32 bits you should be able to reference the whole range [0, 0xFFFFFFFF], no?

IMPORTANT NOTE: The term "memory index" is ambiguous and confusing. The linked article refers strictly to array indexes, not addresses in memory. It is entirely valid for size_t to be incapable of representing all memory addresses, which is why we have the intptr_t type in C99. Of course, this doesn't apply to your workstation, which undoubtedly has a simple Von Neumann type architecture. (The question has since been edited to remove references to "memory indexes".)

The C standard guarantees that size_t can hold the size of any array. However, for any array a[N], the standard guarantees that a + N must be a valid pointer and compare not equal to any pointer to an element of a.

Therefore, size_t must be able to represent at least one value larger than any possible array index. Since ~(size_t)0 is guaranteed to be the maximum size_t value, it is a good choice of sentinel for array indexes.

Discussion:

  1. Why is ~(size_t)0 guaranteed to be the maximum? Because the standard explicitly says so: from §6.5.3.3: "If the promoted type is an unsigned type, the expression ~E is equivalent to the maximum value representable in that type minus E." Note that (size_t)-1 is guaranteed to also be the maximum by the rules of conversion from signed to unsigned types. Unfortunately, it is not always easy to find the definition for SIZE_MAX on your platform, so (size_t)-1 and ~(size_t)0 are preferred.

  2. What is the size of an array indexed from 0 to ~0? Such an array cannot exist according to the C standard, by the argument outlined at the top of this post.

  3. If you malloc(-1), the resulting memory region would have to start at 0. (FALSE) There are a lot of really bizarre cases which the standard allows but one doesn't encounter in practice. For example, imagine a system where (uintptr_t)-1 > (size_t)-1. The C standard is worded in exactly the way it is because it doesn't just run on your PC, it runs on bizarre little DSPs with Harvard architectures, and it runs on archaic systems with byzantine memory segmenting schemes. There are also some systems of historical interest where NULL pointers do not have the same representation as 0.

To "if, if, if" or to "if, else if, else if, else"

18 votes

I am writing some code for data analysis, and have to exclude samples based on some criteria. In practice I end up writing code such as:

bool Test(SampleType sample)
{
  if( ! SubTest1(sample) )
    return false;
  if( ! SubTest2(sample) )
    return false;
  if( ! SubTest3(sample) )
    return false;

  return true;
}

The following seems equivalent to me:

bool Test(SampleType sample)
{
  if( ! SubTest1(sample) )
    return false;
  else if( ! SubTest2(sample) )
    return false;
  else if( ! SubTest3(sample) )
    return false;
  else 
    return true;
}

Is there a difference in terms of computing cost? Is there a arguable preferential one in terms of extendibility/maintainability, aesthetics, etc...?

I know this is probably an inconsequential issue, but once I get these questions stuck in my head I NEED to find the answer.

PS: in case anyone cares, my actual code as of 15/09 can be found at the following: http://folk.uio.no/henrikq/conf.tgz

Compiler generates the same code for both the versions. But the 1st version is better in maintainability aspect if you compare just with the 2nd version.

The code exits when the return statement is encountered; so there is no use of keeping else in the upcoming if. It makes the developer understand the code better.

Also, if this is the literal code then you can still shrink as,

bool Test(SampleType sample)
{
  return (SubTest1(sample) && SubTest2(sample) && SubTest3(sample));
}

Is '\0' guaranteed to be 0?

17 votes

I wrote this function in C, which is meant to iterate through a string to the next non-white-space character:

char * iterate_through_whitespace(unsigned char * i){
    while(*i && *(i++) <= 32);
    return i-1;
}

It seems to work quite well, but I'm wondering if it is safe to assume that the *i will be evaluated to false in the situation that *i == '\0', and it won't iterate beyond the end of a string. It works well on my computer, but I'm wondering if it will behave the same when compiled on other machines.

The standard says:

A byte with all bits set to 0, called the null character, shall exist in the basic execution character set; it is used to terminate a character string.

Efficient way to convert a 16-bit short array to a 32-bit int array?

16 votes

What is the most efficient way to convert an array of unsigned short numbers (16 bits per value) into an array of unsigned ints numbers (32 bits per value)?

Copy it.

unsigned short source[]; // …
unsigned int target[]; // …
unsigned short* const end = source + sizeof source / sizeof source[0];
std::copy(source, end, target);

std::copy internally choses the best copying mechanism for given input types. In this case, however, there’s probably no better way than copying the elements individually in a loop.

15 votes

I need to understand memory fences in multicore machines. Say I have this code

Core 1

mov [_x], 1; mov r1, [_y]    

Core 2

mov [_y], 1; mov r2, [_x]

Now the unexpected results without memory fences would be that both r1 and r2 can be 0 after execution. In my opinion, to counter that problem, we should put memory fence in both codes, as putting it to only one would still not solve the problem. Something like as follows...

Core 1

mov [_x], 1; memory_fence; mov r1, [_y]  

Core 2

mov [_y], 1; memory_fence; mov r2, [_x]

Is my understanding correct or am I still missing something? Assume the architecture is x86. Also, can someone tell me how to put memory fences in a C++ code?

Fences serialize the operation that they fence (loads & stores), that is, no other operation may start till the fence is executed, but the fence will not execute till all preceding operations have completed. quoting intel makes the meaning of this a little more precise (taken from the MFENCE instruction, page 3-628, Vol. 2A, Intel Instruction reference):

This serializing operation guarantees that every load and store instruction that precedes the MFENCE instruction in program order becomes globally visible before any load or store instruction that follows the MFENCE instruction.1

  1. A load instruction is considered to become globally visible when the value to be loaded into its destination register is determined.

Using fences in C++ is tricky (C++11 may have fence semantics somewhere, maybe someone else has info on that), as it is platform and compiler dependent. For x86 using MSVC or ICC, you can use the _mm_lfence, _mm_sfence & _mm_mfence for load, store and load + store fencing (note that some of these are SSE2 instructions).

Note: this assumes an Intel perspective, that is: one using an x86 (32 or 64 bit) or IA64 processor

In C, does a pointer to a structure always point to its first member?

Asked on Mon, 05 Sep 2011 by Steve c
15 votes

Suppose I have a number of C structs for which I would like a particular set of functions to operate upon.

I'm wondering if the following is a legitimate approach:

typedef struct Base {
     int exampleMember;
     // ...
} Base;

typedef struct Foo {
     Base base;
     // ...
} Foo;

typedef struct Bar {
     Base base;
     // ...
} Bar;

void MethodOperatesOnBase(void *);

void MethodOperatesOnBase(void * obj)
{
     Base * base = obj;
     base->exampleMember++;
}

In the example you'll notice that both structs Foo and Bar begin with a Base member.

And, that in MethodOperatesOnBase, I cast the void * parameter to Base *.

I'd like to pass pointers to Bar and pointers to Foo to this method and rely on the first member of the struct to be a Base struct.

Is this acceptable, or are there some (possibly compiler-specific) issues I need to be aware of? (Such as some sort of packing/padding scheme that would change the location of the first member of a struct?)

Yes, the C standard specifically guarantees that this will work.

(C1x §6.7.2.1.13: "A pointer to a structure object, suitably converted, points to its initial member ... and vice versa. There may be unnamed padding within as structure object, but not at its beginning.")

What exactly is a type cast in C/C++?

15 votes

What exactly is a type cast in C/C++? How does the compiler check if an explicit typecast is needed (and valid)? Does it compare the space required for an value? If I have for example:

int a;
double b = 15.0;
a = (int) b;

If I remember correctly a double value requires more space (was it 8 bytes?!) than an integer (4 bytes). And the internal represantation of both are completely different (complement on two/mantissa). So what happens internally? The example here is quite straightforward, but in C/C++ there are plentiful typecasts. How does the compiler know (or the programmer if I can cast e.g. FOO to BAR)?

A type cast is basically a conversion from one type to another. It can be implicit (i.e., done automatically by the compiler, perhaps losing info in the process) or explicit (i.e., specified by the developer in the code). The space occupied by the types is of secondary importance. More important is the applicability (and sometimes convenice) of conversion.

It is possible for implicit conversions to lose information, signs can be lost / gained, and overflow / underflow can occur. The compiler will not protect you from these events, except maybe through a warning that is generated at compile time. Slicing can also occur when a derived type is implicitly converted to a base type (by value).

For conversions that can be downright dangerous (e.g., from a base to a derived type), the C++ standard requires an explicit cast. Not only that, but it offers more restrictive explicit casts, such as static_cast, dynamic_cast, reinterpret_cast, and const_cast, each of which further restricts the explicit cast to only a subset of possible conversions, reducing the potential for casting errors.

Valid conversions, both implicit and explict are ultimately defined by the C/C++ standards, although in C++, the developer has the ability to extend conversions for user defined types, both implicit and explicit, via the use of constructors and overloaded (cast) operators.

The complete rules for which casts are allowed by the standards and which are not can get quite intricate. I have tried to faithfully present a somewhat concise summary of some of those rules in this answer. If you are truly interested in what is and is not allowed, I strongly urge you to visit the standards and read the respective sections on type conversion.

Is it safe to allocate too little space (if you know you won't need it)?

13 votes

So C99 blessed the commonly-used "flexible array member" hack to allow us to make structs that could be overallocated to suit our size requirements. I suspect it's perfectly safe on most sane implementations to do this, but is it legal in C to "underallocate" if we know in certain situations that we won't need some members of a struct?

Abstract Example

Say I have a type:

struct a {
  bool   data_is_x;
  void * data;
  size_t pos;
};

If data_is_x, then the type of data is a type that needs to use the pos member. Otherwise, the functions that work with this struct won't need the pos member for this particular copy of the struct. Essentially, the struct carries around information about whether or not it has a pos member, and this information will not be changed within the struct's lifetime (outside of evil mischief, which will break pretty much anything anyway). Is it safe to say:

struct a *a = malloc(data_is_x ? sizeof(struct a) : offsetof(struct a, pos));

which will allocate space for a pos member only if one is needed? Or does it violate a constraint to use cast space that is too small to a struct pointer, even when you never use the members in question?

Concrete Example

My real-world use case is a bit involved; it's here mainly so you can understand why I want to do this:

typedef struct {
  size_t size;
  void * data;
  size_t pos;
} mylist;

The code for mylist_create specifies that, for size > 0, data is an array of contiguous data that is size items long (whatever an item may be), but that for size == 0 it is the current node of a doubly-linked list containing the items. All the functions that work with mylists will check whether size == 0. If it does, they'll handle the data as a linked list with the "current" index being whichever node data points to. If not, they'll handle the data as an array with the "current" index stored in pos.

Now if size == 0 we don't really need the pos member, but if size > 0 we will. So my question is, is it legal to do this:

mylist *list = malloc(size ? sizeof(mylist) : offsetof(mylist, pos));

If we guarantee (on penalty of undefined behavior) that, while size == 0, we will never try to (or need to) access the pos member? Or does it say somewhere in the standard that it's UB to even think about doing this?

malloc itself doesn't care at all how much memory you allocate for a structure, it's the dereferencing of memory outside the block that is undefined. From C99 6.5.3.2 Address and indirection operators:

If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

And, from 7.20.3 Memory management functions, we find (my italics):

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated).

Hence, you can do something like:

typedef struct { char ch[100]; } ch100;
ch100 *c = malloc (1);

and, provided you only ever try to do anything with c->ch[0], it's perfectly acceptable.


For your specific concrete example, I'm not too sure I'd be that worried, assuming that what you're concerned about is storage space. If you're concerned for other reasons, feel free to ignore this bit, especially since the assumptions included within are not mandated by the standard.

From my understanding, you have a structure:

typedef struct {
  size_t size;
  void * data;
  size_t pos;
} mylist;

where you want to use only data where size is 0, and both data and pos where size is greater than 0. This precludes the use of putting data and pos in a union.

A significant number of malloc implementations will round up your requested space to a multiple of 16 bytes (or some greater power of two) in order to ease memory fragmentation issues. This isn't required by the standard of course, but it is pretty common.

Assuming (for example) 32-bit pointers and size_t, your twelve bytes of structure will most likely take up a 16-byte arena header and a 16-byte chunk for the data. This chunk would still be 16 bytes even if you only asked for 8 (ie. without pos).

If you had 64-bit pointer and size_t types, it might make a difference - 24 bytes with pos and 16 without.

But even then, unless you're allocating a lot of these structures, it may not be a problem.

3 questions about extern used in a Objective-C project

6 votes

1 when I use the word "extern" before a method or variable declaration, am I making it global and therefore readable/writable/usable over the entire project ?

2 If I use extern before a keyword, is there any chance it is still not accessible by part of my project ? For example, only by subclasses.. such as when I use "protected".

3 extern is C keyword right ? Is there an equivalent in Objective C ? I actually don't understand why they use C keyword in an objectiveC project.

thanks

1) you're specifying its linkage. extern linkage allows you or any client to reference the symbol.

regarding global variables: if the variable is mutable and/or needs proper construction, then you should consider methods or functions for this object. the notable exception to this is NSString constants:

// MONClass.h
extern NSString* const MONClassDidCompleteRenderNotification;
// MONClass.m
NSString* const MONClassDidCompleteRenderNotification = @"MONClassDidCompleteRenderNotification";

2) there is no case where the extern keyword affects visibility (public/protected/private/package). to use the symbol (e.g. the constant or C function), simply include the header it is declared in.

somewhat confusing if you are new to the language: placing extern C declarations (constants, functions) in between @interface ... @end will not alter its scope:

@interface MONClass : NSObject

extern const size_t MaximumThreads;

@end

has the same scope (global) and visibility (public) as:

@interface MONClass : NSObject

@end

extern const size_t MaximumThreads;

so it really makes no sense to place your class related C constants or functions in the @interface...@end and @implementation...@end. i recommend placing these in the same header as the interface, outside @interface/@end and @implementation/@end and prefixing the name with the class it is associated with, like so:

@interface MONClass : NSObject

@end

extern const size_t MONClassMaximumThreads;
// MONClass.m
const size_t MONClassMaximumThreads = 23;

and if you want that constant to be private, just declare and define it like this:

// MONClass.m
static const size_t MONClassMaximumThreads = 23;

@implementation MONClass

@end

unfortunately, there is no equally simple or common way to make this constant protected with objc.

finally, you can also use class methods if the number should vary by class:

@interface MONMammal : NSObject
+ (NSUInteger)numberOfLegs;
@end

@implementation MONDog
+ (NSUInteger)numberOfLegs { return 4; }
@end
@implementation MONHuman
+ (NSUInteger)numberOfLegs { return 2; }
@end

3) yes, among other languages. for example, if you use extern const int Something in a c++ translation, the c++ translation will look for Something declared as an extern C++ symbol. there is no substitution in objc; objc is a superset of C and inherits all of C's functionalities. use of extern is well formed and you can also find it in the frameworks you use (e.g. Foundation). they use it because they need to specify linkage. objc does not offer a substitute, presumably because it did not require a replacement or extension.

to avoid this, simply use a #define like this:

#if !defined(__cplusplus)
#define MONExternC extern
#else
#define MONExternC extern "C"
#endif

MONExternC const size_t MONClassMaximumThreads;

Is divide slower than Multiply?

5 votes

Ok, this might sound like a strange question but it is an interesting one. I am coding for iOS and have been told that it is always best to multiply rather than divide values as it is faster.

I know that processors these days probably make this a non issue but my curiosity has gotten the better of me and I am wondering if anyone might be able to shed some light on this for me.

SO..... My question is this -
is:

player.position = ccp(player.contentSize.width / 2, winSize.height / 2);

slower than:

player.position = ccp(player.contentSize.width * 0.5, winSize.height * 0.5);

On most processors division is slower than multiplication for the same data types. In your example your multiplication is a floating point operation, if width and height are integer types, the result may be very different and may depend on both your processor and your compiler.

However most compilers (certainly GCC) will translate a division by a constant power-of-two as in your example, to a right-shift where that would be more efficient. That would generally be faster than either a multiply or divide.