ghostbody / 15-cpp-learning

15 c++ learning repository of SDCS SYSU
6 stars 3 forks source link

Huawei Internship Interview Questions Summary #3

Open ghostbody opened 8 years ago

ghostbody commented 8 years ago

Well, I think I am very lucky to have some simple technology questions this time.

1. Tell the difference of the flowing C statement. (1) char * const p (2) char const * p (3) const char * p

Answer: (1) const pointer p indicate the pointer can't point to other char after definition. (2) and (3) indicates the string is a const string which means that the content is read only.

Summary: Observe that which is nearer to p, * or const. If * is nearer, than this is the latter. Otherwise, the former.

2. Tell the what's wrong with the following c program:

int countAs(char s[]) {
   int length = sizeof(s) / sizeof(char);
   int i, result = 0;
   for(i = 0; i < length; i++) {
     if(s[i] == 'A' || s[i] == 'a') {
       result++;
     }
   }
  return result;
}

Answer: sizeof(s) does not work, because you lost the length of the array in C when you passing it as an parameter. It becomes a pointer. sizeof(s) is a unchanged value.

Question: What is the value?

Answer: In 32 bits operation system, sizeof(s) is 4 while in 64 bits operation system, 8.

Question: How can you fix it?

Answer: pass one more argument indicates the length of the array.

Question: And other methods?

Answer: Using strlen() function to calculate the length of the string.

Question: What should you pay attention to when you use strlen()?

Answer: Well, you should check NULL pointers when the parameters is passed in and also there should be a '\0' char at the end of the string.

Question: And other methods?

Answer: It's unnecessary to calculate the length of the string. You can just use the '\0' char to know the end of the string when you write for loop.

Question: What other problem about the function?

Answer: The argument does not have side effect in this case, it should be made const. Also the return type int may be overflow in the case the string is too long. And the name of the function is not good in some way, make it "count_letter_a".

Interviewer: Your level of knowledge is OK. Talk about one of your project experience......

lscraft commented 8 years ago

Wow,I really hate the problems about const,thanks.

DaddyTrap commented 8 years ago

Um........ Does OK means "不错" or "还行"? THX for your sharing, and I have something interesting to share about the keywordconst.

A different trick

Summary: Observe that which is nearer to p, * or const. If * is nearer, than this is the latter. Otherwise, the former.

It is really a useful trick!!!! Additionally, I have another way to distinguish them. Just observe what is on the right to "const".

For example: const int **a means **a is read-only, while int const **a is the same. int* const *a means *a is read-only int** const a means a is read-only

(Please BE AWARE that the former asterisk:() means the type is pointer, however, the latter means dereference)

The following is my test code, and I think I am right.

int main() {
  int a = 0, b = 2;
  int *pa = &a, *pb = &b;
  int **ppa_1 = &pa;
  const int **ppa_2 /* = &pa*/;
  int const **ppa_3 /* = &pa*/;
  int *const *ppa_4 = &pa;
  int **const ppa_5 = &pa;

  ppa_1 = &pb;
  *ppa_1 = pb;
  **ppa_1 = b;

  // ppa_2 = &pb;
  *ppa_2 = pb;
  **ppa_2 = b;

  // ppa_3 = &pb;
  *ppa_3 = pb;
  **ppa_3 = b;

  ppa_4 = &pb;
  *ppa_4 = pb;
  **ppa_4 = b;

  ppa_5 = &pb;
  *ppa_5 = pb;
  **ppa_5 = b;

  return 0;
}

And the next is the Compile Error Information.

test.cpp: In function 'int main()':
test.cpp:16:11: error: assignment of read-only location '* * ppa_2'
   **ppa_2 = b;
           ^
test.cpp:20:11: error: assignment of read-only location '* * ppa_3'
   **ppa_3 = b;
           ^
test.cpp:23:10: error: assignment of read-only location '* ppa_4'
   *ppa_4 = pb;
          ^
test.cpp:26:9: error: assignment of read-only variable 'ppa_5'
   ppa_5 = &pb;
         ^

Other problems

My code has some lines commented because I got some "Invalid conversion" errors before I make them commented. The errors are following.

test.cpp:5:24: error: invalid conversion from 'int**' to 'const int**' [-fpermissive]
   const int **ppa_2 = &pa;
                        ^
test.cpp:6:24: error: invalid conversion from 'int**' to 'const int**' [-fpermissive]
   int const **ppa_3 = &pa;
                        ^
test.cpp:14:9: error: invalid conversion from 'int**' to 'const int**' [-fpermissive]
   ppa_2 = &pb;
         ^
test.cpp:18:9: error: invalid conversion from 'int**' to 'const int**' [-fpermissive]
   ppa_3 = &pb;
         ^

I don't know why these conversions are invalid. I think I have to learn this part later.

ghostbody commented 8 years ago

@DaddyTrap Perfect Summary. Maybe you can make an issue and I can put your link separately in the home page.

About "const" in Assignment

Just remember one rule that left operand can be assigned if and only if the left operand has more modifiers than the right operand

You use C++ to think about this question. The assignment operator is a member function for the pointer class. Think about the following class:

class pointer {
private:
  int * p;
public:
  pointer& operator=(pointer &another) { this->p = another.p}
}

and also

class pointer {
private:
  int * p;
public:
  pointer& operator=(const pointer &another) { this->p = another.p}
}

can the flowing program run for the two classed respectively?

pointer pointer1;
pointer pointer2 = pointer1;
const pointer3 = pointer2;
pointer2 = pointer3;

Obviously, this is a type translation trick.

There is a ISO C++ standard. Have a look at it and hope it will help you. ISO C++ Const

DaddyTrap commented 8 years ago

@ghostbody I read that page but at first I can't understand until I do an experiment by myself. (It is no doubt that Do It Yourself helps a lot!!)

As the page says

the compiler would like to help you keep your promises not to modify const values. I think this is the main and only principle of the conversion about const.

It just means _"You can't change the const things"_. This may be the only principle.

Here, I regard const as a promise. Promise not to change that variable.

For example.

const int a = 1; // "a" is read-only
int *pa = &a; // This does not promise "a" is read-only, so it is illegal.

int b = 1; // b is not read-only
int *pb = &b; // pb and *pb are not read-only
const int **ppb_c = &pb; // This is illegal!!! Here, in declaration, we promise **ppb_c is read-only.
                         // However, "pb" does not promise *pb is read-only, which means maybe we can change *pb (which is also **ppb_c). So, we can't fulfill
                         // the requirement that **ppb_c is read-only.
int **ppb = &pb; // This is legal.

So, when we can't fulfill the const's promise (the promise that the variable is read-only), we will fail to make the conversion.

Summary: Remember your promises and keep your promises.


So, may I make a new issue in this repository and just copy here's comment?

jianjieluo commented 8 years ago

learn a lot. After doing the similar experiences, I agree with what +c's summary. I think maybe all the usage of 'const' should fulfill this promise, not about the const pointer only.


Yesterday one of my high school classmates asked me a question:

int& Complex::operator[] (int par) const {
  if (par == 0) return real;
  else return imag;
}

It is a override [] in a Complex class. The compiler gave such an error:

'return' : cannot convert from 'const int ' to 'int &'

so it should be the same problem, for if we return an int&, we can't promise we change the value.


I think that in our opinion at the beginning, we might think that if we don't change the value, it's OK. However, we can't keep our promise when the code becomes longer and longer. So the compiler just give such a limit to make our code more safety..


Is my thinking right? I am not so sure. @DaddyTrap