简体   繁体   中英

Odd behaviour of round brackets in objective-c

i was wondering why my code not work as i suppose to. Please consider the following code:

- (NSString *)bake {
    return [NSString stringWithFormat:(@"Take %@, put it in oven for 30 minutes, add 250 gramm of %@ cheese, many %@ toppings and little drop of %@ sauce", [self dough], [self cheese], [self toppings], [self sauce])];
}

- (NSString *)cut {
    return [NSString stringWithFormat:(@"Cut in 4 pieces")];
}

- (NSString *)box {
    return [NSString stringWithFormat:(@"Box pizza. Ready for sale!")];
}

- (NSString *)orderString {
    return [NSString stringWithFormat:@"%@ %@ %@", [self bake], [self cut], [self box]];
}

Pretty straightforward. Now, output result in console is (that is what orderString contain):

Tobasko Cut in 4 pieces Box pizza. Ready for sale!

Look like for some reason, we got only last word from text contained in bake NSString . And compiler even warn this line of code with 2 "yellow" warnings:

Format string is not a string literal (potentially insecure)

Expression result unused

I solve that problem simply by remove round brackets like that:

return [NSString stringWithFormat:@"Take %@, put it in oven for 30 minutes, add 250 gramm of %@ cheese, many %@ toppings and little drop of %@ sauce", [self dough], [self cheese], [self toppings], [self sauce]];

However, i don't understand, why compiler truncate my string when i simply put statement in round brackets?

The parentheses (not round brackets) group everything inside it into an expression. It useful to change the precedence of certain operators or to make code more readable.

In C based languages (including Objective-C), the value of a series of comma separated expressions is the value of the last expression in the list.

The parentheses in your line end up grouping the separate parameters to the stringWithFormat: method into a single argument instead of the expected separate set of arguments.

So the value of:

(@"Take %@, put it in oven for 30 minutes, add 250 gramm of %@ cheese, many %@ toppings and little drop of %@ sauce", [self dough], [self cheese], [self toppings], [self sauce])

is just the value of the last one:

[self sauce]

So in affect, your line is really just:

return [NSString stringWithFormat:[self sauce]];

which is why you get the two warnings and why it only returns Tobasko .

Further, the use of NSString stringWithFormat: should always have at least two parameters. The first should be a string with at least one format specifier and the remaining parameters should correspond to each of the format specifiers in the format string.

So code like:

return [NSString stringWithFormat:(@"Cut in 4 pieces")];

Has two problems. 1. Pointless parentheses and 2. There's no need to use stringWithFormat: . Just use:

return @"Cut in 4 pieces";

I think to understand what is happening, we need to break it down into 3 aspects:

  1. [NSString stringWithFormat:] takes 1 or more arguments. You can pass in just a string, with no other arguments, and it will return just that string. If you have format descriptors in the string (eg %@ , %d , etc.) then a matching number of additional parameters are required. But again, a single string with no format descriptors is a valid parameter.

  2. The parentheses () signify that the contents inside the parentheses should first be evaluated and then used as a single expression

  3. The comma operator in C means, roughly, "evaluate these expressions from left to right and return the value of the rightmost expression"

http://crasseux.com/books/ctutorial/The-comma-operator.html

So what is happening in your "bake" method is:

  1. Evaluate the contents of the parentheses first as a single expression
  2. Since the contents of the parentheses are comma-separated, evaluate each expression left to right, and return the value of the rightmost expression (in this case [self sauce] , which evaluates to @"Tabasko" )
  3. Use this single expression as the parameter for [NSString stringWithFormat:] , ie [NSString stringWithFormat:@"Tabasko"];

All of your other methods before "orderString" are just single string parameters anyway, so the parentheses don't make a difference in the final result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM