SoFunction
Updated on 2025-04-09

Swift and C language mixed programming tutorial

As a language that can be called with Objective-C, Swift also has some types and features with C language. If your code needs it, Swift also provides a programming method that mixes programming with common C code structures.

Basic data types

Swift provides some basic data types of Swift that are equivalent to C language such as char, int, float, and double. However, these core primitive types of Swift cannot be implicitly converted to each other, such as Int. So only your code explicitly requires them to use these types again, and Int can be used whenever you want to use it.

Type C Swift Type
bool CBool
char, signed char CChar
unsigned char CUnsignedChar
short CShort
unsigned short CUnsignedShort
int CInt
unsigned int CUnsignedInt
long CLong
unsigned long CUnsignedLong
long long CLongLong
unsigned long long CUnsignedLongLong
wchar_t CWideChar
char16_t CChar16
char32_t CChar32
float CFloat
double CDouble

enumerate

Swift introduces any C-style enumeration type marked with the macro NS_ENUM. This means that no matter whether the enum values ​​are defined in the system framework or in custom code, their prefix names will be truncated when they are imported into Swift. For example, look at this Objective-C enum:

Copy the codeThe code is as follows:

//Objective-C
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

In Swift, this is done:
Copy the codeThe code is as follows:

//Swift
enum UITableViewCellStyle: Int {
    case Default
    case Value1
    case Value2
    case Subtitle
}

When you need to point to an enum value, use the enum name that starts with a dot (.):

Copy the codeThe code is as follows:

//Swift
let cellStyle: UITableViewCellStyle = .Default

Swift also introduced the option marked NS_OPTIONS macro. While the behavior of options is similar to the introduced enumeration, options can also support some bit operations, such as &, | and ~. In Objective-C, you set the mark to zero (0) with an empty option. In Swift, using nil means there is no option.

pointer

Swift avoids giving you direct access to pointers as much as possible. However, when you need to manipulate memory directly, Swift also provides you with multiple pointer types. The following table uses Type as the placeholder type name to represent the syntax mapping.
For parameters, use the following mapping:

C Syntax Swift Syntax
const void * CConstVoidPointer
void * CMutableVoidPointer
const Type * CConstPointer<Type>
Type * CMutablePointer<Type>


For multi-level pointers of return types, variables, and parameter types, use the following mappings:

C Syntax Swift Syntax
void * COpaquePointer
Type * UnsafePointer<Type>


For class types, use the following mapping:

C Syntax Swift Syntax
Type * const * CConstPointer<Type>
Type * __strong * CMutablePointer<Type>
Type ** AutoreleasingUnsafePointer<Type>

C Variable pointer

When a function is declared to accept the CMutablePointer<Type> parameter, the function can accept any of the following types as a parameter:

•nil, passed in as a null pointer
• A value of type CMutablePointer<Type>
• An operand is an input and output expression of the lvalue of type Type, which is passed in as the memory address of this lvalue
• An input-output Type[] value is passed as the starting pointer of an array, and its life cycle will be extended during this call

If you declare a function like this:

Copy the codeThe code is as follows:

//Swift
func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ }

Then you can call this function using any of the following ways:

Copy the codeThe code is as follows:

//Swift
var x: Float = 0.0
var p: CMutablePointer<Float> = nil
var a: Float[] = [1.0, 2.0, 3.0]

takesAMutablePointer(nil)
takesAMutablePointer(p)
takesAMutablePointer(&x)
takesAMutablePointer(&a)

When a function is declared to use a CMutableVoidPointer parameter, the function accepts any Type operand of type similar to CMutablePointer<Type>.

If you define a function like this:

Copy the codeThe code is as follows:

//Swift
func takesAMutableVoidPointer(x: CMutableVoidPointer) { /* ... */ }

Then you can call this function using any of the following ways:

Copy the codeThe code is as follows:
//Swift
var x: Float = 0.0, y: Int = 0
var p: CMutablePointer<Float> = nil, q: CMutablePointer<Int> = nil
var a: Float[] = [1.0, 2.0, 3.0], b: Int = [1, 2, 3]

takesAMutableVoidPointer(nil)
takesAMutableVoidPointer(p)
takesAMutableVoidPointer(q)
takesAMutableVoidPointer(&x)
takesAMutableVoidPointer(&y)
takesAMutableVoidPointer(&a)
takesAMutableVoidPointer(&b)

C always pointer

When a function is declared to accept the CConstPointer<Type> parameter, the function can accept any of the following types as a parameter:

•nil, passed in as a null pointer
•A CMutablePointer<Type>, CMutableVoidPointer, CConstPointer<Type>, CConstVoidPointer, or convert to CConstPointer<Type> AutoreleasingUnsafePointer<Type> value if necessary
• An operand is an input and output expression of the lvalue of type Type, which is passed in as the memory address of this lvalue
•A Type[] array value is passed as the starting pointer of an array, and its life cycle will be extended during this call

Copy the codeThe code is as follows:

//Swift
func takesAConstPointer(x: CConstPointer<Float>) { /*...*/ }

Then you can call this function using any of the following ways:

Copy the codeThe code is as follows:

//Swift
var x: Float = 0.0
var p: CConstPointer<Float> = nil

takesAConstPointer(nil)
takesAConstPointer(p)
takesAConstPointer(&x)
takesAConstPointer([1.0, 2.0, 3.0])

When a function is declared to use a CConstVoidPointer parameter, the function accepts any Type operand of type similar to CConstPointer<Type>.  If you define a function like this:

Copy the codeThe code is as follows:

//Swift 
func takesAConstVoidPointer(x: CConstVoidPointer) { /* ... */ }

Then you can call this function using any of the following ways:

Copy the codeThe code is as follows:

//Swift
var x: Float = 0.0, y: Int = 0
var p: CConstPointer<Float> = nil, q: CConstPointer<Int> = nil

takesAConstVoidPointer(nil)
takesAConstVoidPointer(p)
takesAConstVoidPointer(q)
takesAConstVoidPointer(&x)
takesAConstVoidPointer(&y)
takesAConstVoidPointer([1.0, 2.0, 3.0])
takesAConstVoidPointer([1, 2, 3])

Automatically release unsafe pointer

When a function is declared to accept the AutoreleasingUnsafePointer<Type> parameter, this function can accept any of the following types as a parameter:

•nil, passed in as a null pointer
•A AutoreleasingUnsafePointer<Type> value
• Its operand is original, copied to a temporary input and output expression of a buffer without an owner, the address of the buffer is passed to the call, and when returned, the value in the buffer is loaded, saved, and reassigned to the operand.

Note: This list does not contain an array.

If you define a function like this:

Copy the codeThe code is as follows:

//Swift
func takesAnAutoreleasingPointer(x: AutoreleasingUnsafePointer<NSDate?>) { /* ... */ }


Then you can call this function using any of the following ways:

Copy the codeThe code is as follows:

//Swift
var x: NSDate? = nil
var p: AutoreleasingUnsafePointer<NSDate?> = nil

takesAnAutoreleasingPointer(nil)
takesAnAutoreleasingPointer(p)
takesAnAutoreleasingPointer(&x)

Note: C function pointers have not been introduced by Swift.

Global constants

Global constants defined in C and Objective-C language source files are automatically introduced by Swift compile and used as global constants for Swift.

Preprocessing instructions

The Swift compiler does not include a preprocessor. Instead, it takes full advantage of compile-time properties, generation configurations, and language features to accomplish the same functionality. Therefore, Swift does not introduce preprocessing instructions.

Simple macro

In C and Objective-C, you usually use a macro constant defined by the #define directive, and in Swift, you can use global constants instead. For example: a global definition #define FADE_ANIMATION_DURATION 0.35 can be used to better express it in Swift. Since simple macros used to define constants are mapped directly into Swift global quantities, the Swift compiler will automatically introduce simple macros defined in C or Objective-C source files.

Complex macros

Complex macros used in C and Objective-C do not have a corresponding definition in Swift. Complex macros are macros that are not used to define constants, but to define macros that contain parentheses (), functions. Your use of complex macros in C and Objective-C is used to avoid type checking limitations and duplicate labor of the same code. However, macros can also cause bugs and refactoring difficulties. In Swift you can directly use functions and generics to achieve the same effect. Therefore, complex macros defined in C and Objective-C source files cannot be used in Swift.

Compile configuration

Swift code and Objective-C code are conditionally compiled in different ways. Swift code can be compiled conditionally based on the evaluation of the generated configuration. The generated configuration includes true and false literals, command line flags, and platform test functions in the following table. You can specify the command line flag using -D <#Flag#>.

function Valid parameters
os() OSX, iOS
arch() x86_64, arm, arm64, i386

Note: The build configuration of arch(arm) does not return true for 64-bit arm devices, and the build configuration of arch(i386) returns true when the code is running on a 32-bit iOS simulator.

A simple conditional compilation requires the following code format:

Copy the codeThe code is as follows:

#if build configuration
    statements
#else
    statements
#endif

A statement declared by zero or more valid Swift statements, which can include expressions, statements, and control flow statements. You can add additional build configuration requirements, conditional compilation instructions with && and | | operators as well! Operator, add conditional control blocks with #elseif:

Copy the codeThe code is as follows:

#if build configuration && !build configuration
    statements
#elseif build configuration
    statements
#else
    statements
#endif

Contrary to conditional compilation of C compilers, Swift conditional compilation statements must be completely self-contained and syntactical-effective code blocks. This is because Swift code must be syntax checked even if it is not compiled.