2009-12-07 3 views
7

Я исхожу из фона Objective-C, и я пытаюсь расширить свои знания в C. Одна вещь меня смутила, но это разница между указателями в C и Obj- C. Как вы можете видеть в приведенных ниже примерах, все выглядит по-другому по-разному между обоими языками, и мне было интересно, можете ли вы объяснить, почему?C указатели против указателей Objective-C

код C работает отлично:

void myFunction() 
{ 
    int x, *pointerX; 
    pointerX = &x; 
    *pointerX = 5; 

    // Prints: "x is 5" 
    printf("x is: %i", x); 
} 

код Obj-C не удается:

- (void)myMethod 
{ 
    NSString *string = @"Caramel coffee", *stringPointer; 
    stringPointer = &string;     // Warning: Assignemnt from incompatible pointer type 
    *stringPointer = @"Chocolate milkshake"; // Exception: Incompatible types in assignment 

    NSLog(@"string is: %@", string); 
} 

Вопрос: Почему я не могу назначить stringPointer на адрес памяти строки (stringPointer = &string;), и почему я могу выполнить *pointerX = 5; под C, но я не могу выполнить *stringPointer = @"Chocolate milkshake"; под Objecti в-C?

Я понимаю, что Obj-C имеет дело с объектами, а C - нет, но я не могу понять детали за кадром, почему он не работает в Obj-C. Любая помощь приветствуется. Благодаря! :)

+0

Вы пытаетесь выяснить часть C или объект Objective-C? Из вашего вопроса, похоже, вы хотите изучить C, но вы пишете Objective-C код, который выглядит как C ... – stefanB

+0

The C part. Прошу прощения за путаницу. Мой фон: я прочитал некоторые книги Objective-C, и теперь я читаю книги C. Меня озадачило то, как указатели работали на C, что казалось немного другим (хотя Obj-C построен поверх C). –

+0

Я уверен, что указатели работают одинаково в C и Objective-C, я думаю, что вы запутываетесь при использовании классов Cocoa, не понимая, как их использовать. Самое простое - найти примеры, чтобы увидеть, как обычно используются классы Cocoa, которые могли бы устранить проблемы, поскольку я сказал, что проблема может быть связана с деревом классов, которое скрыто за классами интерфейса, с которыми вы имеете дело. – stefanB

ответ

18

В вашем первом примере x и pointerX имеют разные типы ((int) и (int *) соответственно). В вашем втором примере string и stringPointer имеют одинаковый тип (NSString *). Попробуйте вместо этого:

NSString *string = @"Caramel coffee", **stringPointer; 
3

&string имеет тип NSString **, в то время как stringPointer имеет тип NSString *, таким образом предупреждение. Затем вы пытаетесь присвоить экземпляр NSString (с типом NSString *) переменной типа NSString, что приведет к ошибке.

10

Ваш NSString *string сам по себе является указателем. Поэтому, чтобы указать на это, вам нужно объявить stringPointer в качестве указателя на указатель. То есть, объявить stringPointer как это:

NSString **stringPointer; 

Тогда все должно работать. Обратите внимание, что в C и Objective-C применяются те же семантики указателя.

2

Это всегда хорошая идея, чтобы определить каждую переменную на своей собственной линии. Когда вы переписываете свой исходный код цели-с, например

NSString* string = @"Caramel coffee"; 
NSString* stringPointer; 

многое становится понятным.

+1

-1 Все еще не исправляет проблему, так как типы указателей несовместимы. –

+0

@Quinn: в момент написания моего сообщения проблема была решена.Может быть, лучше писать такие сообщения, связанные с стилем, в комментариях, но тогда нет возможности форматирования кода. – Wildcat

1

Вопрос в том, что ваши строки являются константами или нет?
Первый пример, вероятно, будет работать.
Даже в некоммунистических компиляторах C, литеральные строки могут быть помещены в память const через компоновщик/параметры компилятора.

На этой строке: stringPointer = & string; Вы копируете адрес указателя в строку poitner. Совершенно несовместимо.

И на этой линии:
* stringPointer = @ "Шоколадный молочный коктейль";

Вы пытаетесь записать строку в указатель (указатель представляет собой 4-байтовый адрес). Не рекомендуется копировать целую строку поверх нее.

0

Что вы пытаетесь сделать?

Не уверен, что он будет работать так, как вы планировали.

Вы, кажется, принимаете концепции с C и применяете их к классам Cocoa, я думал, что вы учите C. Вы видели где-нибудь в коде Objective-C, принимающем адрес объекта?

Классы какао реализованы с использованием Class clusters, что означает, что они имеют один и тот же интерфейс, но вы получите определенный расширенный класс, которым вы управляете.

В вашем случае вы принимаете адрес возможного класса, который расширяет NSString и назначает его указателю на NSString.

Пример:

NSString * str = @"Caramel coffee"; 
NSString * str2 = [NSString stringWithString:@"all"]; 

NSLog(@"%@", [[str class] className]); 
NSLog(@"%@", [[str class] className]); 

Output (GNUStep линукс):

2009-12-08 10:49:29.149 x[25446] GSCInlineString 
2009-12-08 10:49:29.149 x[25446] NSConstantString 

... кроме очевидных проблем определения указатель указывал на другие.

+0

Шаблон NSError, вероятно, является наиболее распространенным случаем, когда мы берем адрес объекта в Objective-C: «Ошибка NSError *; [[NSFileManager defaultManager] contentsOfDirectoryAtPath: @" foo "error: & error]; –

+0

Да, но мы передаем адрес локальной переменной в метод, потому что мы ожидаем возвращаемого значения. Но вы обычно не видите такие вещи, как 'NSString * str = & someotherNSStringObject;' – stefanB

5

Дело в том, что при создании объекта вы фактически всегда манипулируете им с помощью назначенного ему указателя, следовательно (NSString *).

Попробуйте сделать то же самое в C (работает со строкой), возможно, становится все яснее:

void myFunction() 
{ 
    char *string = "this is a C string!"; 
    char **ptr=&string; 


    // Prints: "this is a c string" 
    printf("ptr points to %s: \n", *ptr); 
} 

Как вы можете видеть, указатели работать точно так же, как они это делают в Objective-C. Готов иметь в виду, что в объекте-c очень мало примитивов (int является наиболее очевидным). В большинстве случаев вы создаете указатель объекта типа X (например, NSString), а затем выделяете кусок памяти (через [[Object alloc] init]) и задаете начальный адрес этого фрагмента указателю. Точно так же, как мы сделали в C с нашей строкой.

Смежные вопросы