Kochan 2.0 Exercise 10-6

Discussion in 'Mac Programming' started by mdeh, Jan 25, 2009.

  1. mdeh
    Expand Collapse
    macrumors 6502

    Jan 3, 2009
    Here is the exercise in full:

    Based on the following definitions

    float f = 1.00;
    short int i = 100;
    long int l = 500L;
    double d = 15.00;

    and the seven steps outlined in this chapter for the conversion of operands in expressions, determine the type and value of the following expressions:

    f + i
    l / d
    i / l + f
    l * i
    f / 2
    i / (d + f)
    l / (i * 2.0)
    l + i / (double) l

    Here is what I **thought** I would try and do.

    someGenericType result;

    result = f + i;

    if (SomeTestToDetermineResult == float)
    NSLOG(@"Result of f + i is a float");

    But quickly ran into problems trying to find a "someGenericType". I **think** what the author means is using the "grammatical rules of syntax, what would you expect to find, as opposed to a program that does what I am trying to do, viz use a generic return data type, then test that type and declare what it is.

    Any ideas?
  2. lee1210
    Expand Collapse
    macrumors 68040


    Jan 10, 2005
    Dallas, TX
    I could not come up with a way to do this in C or Objective-C (take an expression and get its type). The typeof gcc extension would allow you to define a new type with the type of an expression, but that still doesn't help.

    Using the sizes you can narrow it down, but it's not an "answer":
    #include <stdio.h>
    const char *type_string(int);
    int main(int argc, char *argv[]) {
      float f = 1.00;
      short int i = 100;
      long int l = 500L;
      double d = 15.00;
      printf("Size of f + i: %d\n",sizeof(f + i));
      printf("Size of l / d: %d\n",sizeof(l / d));
      printf("Size of i / l + f: %d\n",sizeof(i / l +f));
      printf("Size of l * i: %d\n",sizeof(l * i));
      printf("Size of f / 2: %d\n",sizeof(f / 2));
      printf("Size of i / (d + f): %d\n",sizeof(i / (d + f)));
      printf("Size of l / (i * 2.0): %d\n",sizeof(l / (i * 2.0)));
      printf("Size of l + i / (double) l: %d\n",sizeof(l + i / (double) l));
      printf("Type of f + i: %s\n",type_string(sizeof(f + i)));
      printf("Type of l / d: %s\n",type_string(sizeof(l / d)));
      printf("Type of i / l + f: %s\n",type_string(sizeof(i / l +f)));
      printf("Type of l * i: %s\n",type_string(sizeof(l * i)));
      printf("Type of f / 2: %s\n",type_string(sizeof(f / 2)));
      printf("Type of i / (d + f): %s\n",type_string(sizeof(i / (d + f))));
      printf("Type of l / (i * 2.0): %s\n",type_string(sizeof(l / (i * 2.0))));
      printf("Type of l + i / (double) l: %s\n",type_string(sizeof(l + i / (double) l)));
      return 0;
    const char *type_string(int in) {
      switch(in) {
          return "unknown type";
        case 1:
          return "char";
        case 2:
          return "short int";
        case 4:
          return "float or int";
        case 8:
          return "double or long int";
        case 12:
        case 16:
          return "long double";
    Note that i am only posting code because i don't think you are supposed to write code for this, but follow the implicit casting/promotion rules to solve this. The results of this program are ambiguous enough that it doesn't give it away for you.

    Since C++ is more type-safe, and allows for overloading functions, you can do this there... I honestly can't say if the rules are the same in C and C++. There is enough else that is different between the two that i wouldn't bet my life on it, but i am pretty sure they are the same in this case. Anyhow, don't run this code unless you want the answers given away:
    #include <iostream>
    #include <string>
    std::string myType(char);
    std::string myType(short int);
    std::string myType(int);
    std::string myType(long int);
    std::string myType(float);
    std::string myType(double);
    std::string myType(long double);
    int main(int argc, char *argv) {
      float f = 1.00;
      short int i = 100;
      long int l = 500L;
      double d = 15.00;
      std::cout <<"Type of f + i: " << myType(f + i) << std::endl;
      std::cout <<"Type of l / d: "<<myType(l / d) << std::endl;
      std::cout <<"Type of i / l + f: "<<myType(i / l +f) << std::endl;
      std::cout <<"Type of l * i: "<<myType(l * i) << std::endl;
      std::cout <<"Type of f / 2: "<<myType(f / 2) << std::endl;
      std::cout <<"Type of i / (d + f): "<<myType(i / (d + f)) << std::endl;
      std::cout <<"Type of l / (i * 2.0): "<<myType(l / (i * 2.0)) << std::endl;
      std::cout <<"Type of l + i / (double) l: "<<myType(l + i / (double) l) << std::endl;
    std::string myType(char in) {
      std::string ret = "char";
      return ret;
    std::string myType(short int in) {
      std::string ret = "short int";
      return ret;
    std::string myType(int in) {
      std::string ret = "int";
      return ret;
    std::string myType(long int in) {
      std::string ret = "long int";
      return ret;
    std::string myType(float in) {
      std::string ret = "float";
      return ret;
    std::string myType(double in) {
      std::string ret = "double";
      return ret;
    std::string myType(long double in) {
      std::string ret = "long double";
      return ret;
    Since you can mix Objective-C and C++, I suppose you could get away with this. The formatting on my couts is a little sloppy, because i was just using s// somewhat haphazardly to turn printfs into couts. Again, I really don't think you are supposed to write code for this.

    I tried to think of something goofy to do in C. I was thinking if there would be some way to get the pointer to the result of an expression (no such luck, at least in GCC), it could be cast to void *, then with some memcpy'ing, typecasting, and dependence on different memory representations of the same value as different types of the same width (double vs. long int, int vs. float) except for 0, one might be able to jury rig something. My attempts failed, but that doesn't mean this is impossible.

    Your idea doesn't quite work out, because the primitives are not classes, so you can't have a generic primitive. For objects there is the option to do introspection at runtime, but there's no option for that sort of thing here. Since you can't overload methods in Objective-C (if you have the same method name, it must have the same argument types and return type), you can't write a class that emulates the C++ behavior above.

    Someone may be more clever than I am and be able to figure out a way to handle this in plain C or Objective-C, but it is definitely impractical, and once more not likely to be what the author was hoping for.

  3. mdeh
    Expand Collapse
    thread starter macrumors 6502

    Jan 3, 2009
    Bravo!!! Great effort...I am impressed.
    I think the conclusion you reached is probably correct. With the author's directive that answers only use the material covered to that point, there is no way to do this other than using the grammatical syntax rules provided earlier in the chapter.
    But...thanks again for the effort.

Share This Page