Why we used double and triple pointer in objective-C or C language? - iphone

I confused when i want to take single pointer and when should i take double pointer?
In following structure what exactly did?
struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list **methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
};
Why we use the methodLists double pointer?
Edited
int sqlite3_get_table(
sqlite3 *db,
const char *zSql,
char ***pazResult,
int *pnRow,
int *pnColumn,
char **pzErrmsg
);
In above scenario what will be meaning of triple pointer char ***pazResult?

Well, in C at least, double-pointers are commonly used for 2D arrays. The most common 2D array is probably an array of C strings (char*'s). Double pointers are also sometimes employed to pass pointers to functions by reference, but this is unlikely to be the use in the code sample you posted.
According to the name methodLists I would guess that this is an array of lists. A (linked) list in C is commonly represented by a pointer to a node, which objc_method_list could be. An array of such lists is then implemented with a double pointer.

It's probably not the case in the code that you referenced, but you also need a double pointer any time you want to pass a pointer to a function and have changes to that pointer be reflected outside the scope of that function.
For example, if you were trying to rewrite the strcpy function so that the user did not have to allocate memory for the source string, you might try something like the following:
void MyStrcpy(char* dst, char* src){
dst = (char*)malloc(sizeof(char)*(strlen(src)+1));
for(int i=0;i<=strlen(src);i++)
dst[i] = src[i];
printf("src: %s ", src);
printf("dst: %s\n\n", dst);
}
If you were then to call that function,
int main() {
char *foo = "foo";
char *newPtr;
MyStrcpy(newPtr, foo);
printf("foo: %s ", foo);
printf("new: %s\n", newPtr);
}
your output would be as follows:
src: foo
dst: foo
foo: foo
new:
You might also get a seg fault when trying to print newPtr, depending your system. The reason for this behavior is the exact same as the reason you wouldn't expect a change to an int that was passed by value to a function to be reflected outside of that function: what you are passing to MyStrcpy is simply the memory address that newPtr references. When you malloc the space for dst inside the function, you are changing the address dst points to. This change will not be reflected outside of the scope of MyStrcpy!
Instead, if you wanted newPtr to point to the new allocated chunk of memory, you need to have dst be a pointer to a pointer, a char **.
void MyStrcpy(char** dst, char* src){
*dst = (char*)malloc(sizeof(char)*(strlen(src)+1));
for(int i=0;i<=strlen(src);i++)
(*dst)[i] = src[i];
printf("src: %s ", src);
printf("dst: %s\n\n", *dst);
}
Now, if you were to call that function:
int main() {
char *foo = "foo";
char *newPtr;
MyStrcpy(&newPtr, foo);
printf("foo: %s ", foo);
printf("new: %s\n", newPtr);
}
You would get your expected output:
src: foo
dst: foo
foo: foo
new: foo
Hope that helps!

See also these questions:
What is double star?
Why does NSError need double indirection? (pointer to a pointer)

In the most general case a double pointer is a pointer to a list of pointers.

In general pointer is used to hold the address of another variable. What if we need to hold the address of pointer ,in that case we use double pointer. When we want to hold the address of double pointer we use triple pointer.

Related

Freeglut doesn't initialize when using it from Swift

I've tried to use the Freeglut library in a Swift 4 Project. When the
void glutInit(int *argcp, char **argv);
function is shifted to Swift, its declaration is
func glutInit(_ pargc: UnsafeMutablePointer<Int32>!, _ argv: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>!)
Since I don't need the real arguments from the command line I want to make up the two arguments. I tried to define **argv in the Bridging-Header.h file
#include <OpenGL/gl.h>
#include <GL/glut.h>
char ** argv[1] = {"t"};
and use them in main.swift
func main() {
var argcp: Int32 = 1
glutInit(&argcp, argv!) // EXC_BAD_ACCESS
glutInitDisplayMode(UInt32(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH));
glutCreateWindow("my project")
glutDisplayFunc(display)
initOpenGL()
glutMainLoop()
but with that I get Thread 1: EXC_BAD_ACCESS (code=1, address=0x74) at the line with glutInit().
How can I initialize glut properly? How can I get an UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>! so that it works?
The reason the right code in C char * argv[1] = {"t"}; does not work is because Swift imports fixed size C-array as a tuple, not a pointer to the first element.
But your char ** argv[1] = {"t"}; is completely wrong. Each Element of argv needs to be char **, but you assign char * ("t"). Xcode must have shown you a warning at first build:
warning: incompatible pointer types initializing 'char **' with an expression of type 'char [2]'
You should better take incompatible pointer types warning as error, unless you know what you are doing completely.
Generally, you should better not write some codes generating actual code/data like char * argv[1] = {"t"}; in a header file.
You can try it with Swift code.
As you know, when you want to pass a pointer to single element T, you declare a var of type T and pass &varName to the function you call.
As argcp in your code.
As well, when you want to pass a pointer to multiple element T, you declare a var of type [T] (Array<T>) and pass &arrName to the function you call.
(Ignoring immutable case to simplify.)
The parameter argv matches this case, where T == UnsafeMutablePointer<Int8>?.
So declare a var of type [UnsafeMutablePointer<Int8>?].
func main() {
var argc: Int32 = 1
var argv: [UnsafeMutablePointer<Int8>?] = [
strdup("t")
]
defer { argv.forEach{free($0)} }
glutInit(&argc, &argv)
//...
}
But I wonder if you really want to pass something to glutInit().
You can try something like this:
func main() {
var argc: Int32 = 0 //<- 0
glutInit(&argc, nil)
//...
}
I'm not sure if freeglut accept this, but you can find some articles on the web saying that this works in some implementation of Glut.

Weird issues when passing an array of structs from Swift to C

I'm passing an array of structs from Swift to a C function. The struct looks like this:
struct Struct {
int a;
float b;
float c;
const char* d;
const char* e;
const char* f;
const char* g;
int h[4];
};
Function signature of the C function:
void test(struct Struct* structs);
Weirdly, when I print d in the C function, it's often something different than what I set it to in the Swift code: usually an empty string or some garbage. When I set d to a very long string, it works correctly. The other strings are passed correctly too. Is that some struct alignment issue?
As #MartinR suggested, when I pass the string to the struct's constructor, Swift creates a temporary C char array on the stack, copies the string's data into it and passes its pointer to the constructor. Immediately after that, the char array is no longer valid. Here's an example code demonstrating this:
let s = Struct(string: "string")
print(s.string) // Prints "string"
print("lol") // Overwrite the stack
print(s.string) // Prints "lol"
See https://stackoverflow.com/a/40121697/243225 for possible solutions.

Converting C char array (unsafe pointer) to String

I have an UnsafeMutablePointer<Character> filled by a CoreFoundation method.
If I NSLog it with %s placeholder, it outputs just fine.
But if I try with Swift's print it just writes the memory address.
Tried nearly everything... also I don't understand why if I try to access the underlying memory property I get a EXC_BAD_ACCESS.
let deviceName = UnsafeMutablePointer<Character>.alloc(64)
/* other statements in which deviceName is filled */
NSLog("device %s by %s", deviceName, manufacturerName)
// Outputs correctly the string
print(String(deviceName[0]))
// Get an EXC_BAD_ACCESS error at runtime
print(String(deviceName.memory))
// Get an EXC_BAD_ACCESS error at runtime
let str = withUnsafePointer(&deviceName) { String.fromCString(UnsafePointer($0)) }
print(str)
// Outputs an empty string
print("\(deviceName) by \(manufacturerName)")
// Outputs just memory addresses
You seem unwilling to show your code, so I can't really help. But this looks just wrong:
let deviceName = UnsafeMutablePointer<Character>.alloc(64)
/* other statements in which deviceName is filled */
That is not how to get hold of a C string in Swift, and if you believe that it is a C string in Swift, you're wrong; it would need to be an array of Int8 (C characters), not Swift Character (a struct!), to be a C string.
In other words, C char (your question's title) is not Swift Character - they are nothing like one another. A C char is a small number, a Swift Character is an object in an object-oriented language that C knows nothing about!

Swift define double pointer for struct defined in c

I have a library which contains this function:
void create_pointer(Pointer **pointer);
It takes a pointer's pointer and allocates memory for it. in c, I can do it like this
Pointer *pointer;
create_pointer(&pointer);
then I have a pointer's instance.
But now I want to use this function in Swift. How?
I have no details about Pointer, I only know it's a struct, defined like this
typedef struct Pointer Pointer;
Let's start with a C example
typedef struct {
NSUInteger someNumber;
} SomeStruct;
void create_some_struct(SomeStruct **someStruct) {
*someStruct = malloc(sizeof(SomeStruct));
(*someStruct)->someNumber = 20;
}
In C, you would use it like this:
//pointer to our struct, initially empty
SomeStruct *s = NULL;
//calling the function
create_some_struct(&s);
In Swift:
//declaring a pointer is simple
var s: UnsafePointer<SomeStruct> = UnsafePointer<SomeStruct>.null()
//well, this seems to be almost the same thing :)
create_some_struct(&s)
println("Number: \(s.memory.someNumber)"); //prints 20
Edit:
If your pointer is an opaque type (e.g. void *), you have to use
var pointer: COpaquePointer = COpaquePointer.null()
Note that Swift is not designed to interact with C code easily. C code is mostly unsafe and Swift is designed for safety, that's why the Swift code is a bit complicated to write. Obj-C wrappers for C libraries make the task much easier.

Using c library in objective c

I'm having trouble creating this c struct in objective c.
typedef struct huffman_node_tag
{
unsigned char isLeaf;
unsigned long count;
struct huffman_node_tag *parent;
union
{
struct
{
struct huffman_node_tag *zero, *one;
};
unsigned char symbol;
};
} huffman_node;
I'm getting this warning at the end of the union type and the end of the struct type above the "unsigned char symbol variable"
warning: declaration does not declare anything
And then when i do something like this:
huffman_node *p = (huffman_node*)malloc(sizeof(huffman_node));
p->zero = zero;
I get this compilation error:
error: 'huffman_node' has no member named 'zero'
Why does this not work? Did i set this up incorrectly? Has anyone experienced this before?
typedef struct huffman_node_tag
{
unsigned char isLeaf;
unsigned long count;
struct huffman_node_tag *parent;
union
{
struct
{
struct huffman_node_tag *zero, *one;
}; // problematic here!
unsigned char symbol;
}; // another problem here!
} huffman_node;
Depending on the C dialect/compiler that is being used to interpret the code, you may not be allowed to declare a struct or union without a name. Try giving them names and see what happens. Alternatively, you may want to try and change the C dialect you are using.
As far as I know anonymous unions are not part of C, but are a compiler extension. So strictly your given struct definition is not valid C. Consequently it seems that objective C does not supports this extension.
You need to include the header for the C library you are using.
You shouldn't have to do much else than that, as Objective C, unlike C++, is a strict superset of C.