You should use the arc4random_uniform()
function. It uses a superior algorithm to rand
. You don't even need to set a seed.
#include <stdlib.h>
// ...
// ...
int r = arc4random_uniform(74);
The arc4random
man page:
NAME
arc4random, arc4random_stir, arc4random_addrandom -- arc4 random number generator
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <stdlib.h>
u_int32_t
arc4random(void);
void
arc4random_stir(void);
void
arc4random_addrandom(unsigned char *dat, int datlen);
DESCRIPTION
The arc4random() function uses the key stream generator employed by the arc4 cipher, which uses 8*8 8
bit S-Boxes. The S-Boxes can be in about (2**1700) states. The arc4random() function returns pseudo-
random numbers in the range of 0 to (2**32)-1, and therefore has twice the range of rand(3) and
random(3).
The arc4random_stir() function reads data from /dev/urandom and uses it to permute the S-Boxes via
arc4random_addrandom().
There is no need to call arc4random_stir() before using arc4random(), since arc4random() automatically
initializes itself.
EXAMPLES
The following produces a drop-in replacement for the traditional rand() and random() functions using
arc4random():
#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))
There seems to be a lot of confusion regarding the preprocessor.
What the compiler does when it sees a #include
that it replaces that line with the contents of the included files, no questions asked.
So if you have a file a.h
with this contents:
typedef int my_number;
and a file b.c
with this content:
#include "a.h"
#include "a.h"
the file b.c
will be translated by the preprocessor before compilation to
typedef int my_number;
typedef int my_number;
which will result in a compiler error, since the type my_number
is defined twice. Even though the definition is the same this is not allowed by the C language.
Since a header often is used in more than one place include guards usually are used in C. This looks like this:
#ifndef _a_h_included_
#define _a_h_included_
typedef int my_number;
#endif
The file b.c
still would have the whole contents of the header in it twice after being preprocessed. But the second instance would be ignored since the macro _a_h_included_
would already have been defined.
This works really well, but has two drawbacks. First of all the include guards have to be written, and the macro name has to be different in every header. And secondly the compiler has still to look for the header file and read it as often as it is included.
Objective-C has the #import
preprocessor instruction (it also can be used for C and C++ code with some compilers and options). This does almost the same as #include
, but it also notes internally which file has already been included. The #import
line is only replaced by the contents of the named file for the first time it is encountered. Every time after that it is just ignored.
Best Answer
void *
means "a reference to some random chunk o' memory with untyped/unknown contents"id
means "a reference to some random Objective-C object of unknown class"There are additional semantic differences:
Under GC Only or GC Supported modes, the compiler will emit write barriers for references of type
id
, but not for typevoid *
. When declaring structures, this can be a critical difference. Declaring iVars likevoid *_superPrivateDoNotTouch;
will cause premature reaping of objects if_superPrivateDoNotTouch
is actually an object. Don't do that.attempting to invoke a method on a reference of
void *
type will barf up a compiler warning.attempting to invoke a method on an
id
type will only warn if the method being called has not been declared in any of the@interface
declarations seen by the compiler.Thus, one should never refer to an object as a
void *
. Similarly, one should avoid using anid
typed variable to refer to an object. Use the most specific class typed reference you can. EvenNSObject *
is better thanid
because the compiler can, at the least, provide better validation of method invocations against that reference.The one common and valid use of
void *
is as an opaque data reference that is passed through some other API.Consider the
sortedArrayUsingFunction: context:
method ofNSArray
:The sorting function would be declared as:
In this case, the NSArray merely passes whatever you pass in as the
context
argument to the method through as thecontext
argument. It is an opaque hunk of pointer sized data, as far as NSArray is concerned, and you are free to use it for whatever purpose you want.Without a closure type feature in the language, this is the only way to carry along a hunk of data with a function. Example; if you wanted mySortFunc() to conditionally sort as case sensitive or case insensitive, while also still being thread-safe, you would pass the is-case-sensitive indicator in the context, likely casting on the way in and way out.
Fragile and error prone, but the only way.
Blocks solve this -- Blocks are closures for C. They are available in Clang -- http://llvm.org/ and are pervasive in Snow Leopard (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/GCD_libdispatch_Ref.pdf).