Doubts while writing practice midterm

  • Can I return arrays from functions in cpp?
    • Returning array pointers like in C works.
    • Cpp way is to use std::vector.
  • 2s complement trick?
    • Flip all bits except the first 1 from the right.
  • Verify when I need to convert to 2s complement while arithmetic.
  • Do I need a colon in a for loop’s i--) {} segment?
    • Nah.
  • Does bit-shifting mutate the original variable?
    • No
  • Bitshifting syntax.
    • i << 1 shifts 1 bit of i to the left.
    • C, Cpp don’t distinguish between i >>> 1 and i >> 1.
      • >>> shifts bits to the right like normal. The new-incoming bits on the left end are 0s.
      • >> shifts bits to the right like normal. The new-incoming bits on the left end are determined based on what was the original left-most bit. Preserves sign.
  • Revise masking.
  • array slicing in cpp.
    • Does not exist with C-style arrays.
    • Might exist with vectors and std::array.
  • Declaring empty arrays and assigning to original arrays.
    • Declaration requires either the contents or an array size.
    • Can’t assign directly, as the variable is just a pointer to the first elem.
    • To copy arrays, you’ll have to loop through.

2’s Complement

  • 2s complement is used to represent sign.
  • For getting the magnitude of a number, we need to get 2s complement of the 2s complement and then get the magnitude.
  • To store neg:
    • Take the positive.
    • Flip the bits.
    • Add 1. Think:
  • For zero, use all 0’s.
  • For positive integers, start counting up, with a maximum of .
  • For negative integers, do exactly the same thing, but switch the role of 0’s and 1’s and count down (so instead of starting with 0000, start with 1111 - that’s the “complement” part).

Reference Local Variables

typename &var_name{ existing_var };
int original_var{1};

Reference var:

int &clone1{original_var};; 
  • Creates an alias for original_var.
  • Does NOT allocate any more memory.
  • It’s literally just introduces a new var name.
int* clone2 = &original_var;
  • Allocates memory for a new variable.

  • clone2’s value is the address of the first.

  • For more: stackoverflow.com

Args vs Parms

  • Arguments are the actual values you pass to a functon.
  • A params is a variable in the func definition.

Pass by Value

  • The argument passed is a copy of the originally passed variable.
  • If you modify the parameter inside the function, the change will not be observed in the original variable.
a = 1
b = 3
void sum(int v1, int v2) {
	v1 += v2;
}
sum(a, b);
  • This doesn’t change the value of a since v1 is a copy of a.

Pass by Reference

There are two ways to think of this:

  • Think like a reference variable: When you pass by reference, you are basically creating a new variable name for the exact same variable.
  • Think with pointers: when you pass by reference, the value which gets “copied” and passed is the memory address of the variable. So when you access using the “copied” pointer, you are actually accessing the contents of the original variable.
a = 1
b = 3
void sum(int* v1, int* v2) {
	*v1 += *v2;
}
sum(&a, &b);

Arrays

Properties

  • Literally a contiguous block of memory where each value is stored next to each other.
  • So if we have int arr[5]; we know it’s gonna take bytes of memory.
  • The actual “value” of arr is the memory address of the first item in the array.
  • The arr[i] notation: Arrays indices are just syntactic sugar for pointers
std::cout 
  << arr << std::endl
  << &arr[0] << std::endl
  << arr[0] << std::endl
  << *arr << std::endl;
  • The first two print the memory address of the first element of the array.
  • The last two print the actual contents of the first element of the array.

Basics

  • Arrays can’t be assigned like regular variables arr_1 = arr_2 will not work.
  • Cpp treats it as a const variable.
  • A const array will not allow you to even change the values inside the array (const squared). int const arr[3]{1, 2, 3}; arr[0] = 0; line two will not work.

Returning from functions

  • Arrays cannot be returned from a function. The array was defined in the returning function and the array gets destroyed once the function is done (stack popping).
  • How are primitives returned then?
    • Returning works by copying the return value and pushing that onto the stack after the function returns.
    • When you make a copy of a primitive, you are actually copying the value.
    • Copying an array, you are copying the address of the first element in the array.
    • So when you return an array, you return address of a dead memory slot.

Passing to functions

  • Need to pass array length separately.
  • Passing by value still leads to passing-by-reference-like behavior.
    • When we pass func(arr) we are essentially passing a copy of the variable arr.
    • Now arr, while semantically represents an array, is actually the memory address of the first element in the array.
    • So we are passing a “copied” value, it’s just that the copied value is a pointer itself.
    • So accessing the array within the function, you access the same memory address.

2s comple