Sadly, gdb is not built-in package for Mac. On Mac, the easiest way to install a package working mainly in CLI such as gdb, gcc, g++, and etc, is to use Brew (Homebrew).
######################################################################## 100.0% ==> Pouring gdb-7.12_1.el_capitan.bottle.tar.gz ==> Caveats gdb requires special privileges to access Mach ports. You will need to codesign the binary. For instructions, see:
the version of gcc is indeed 4.2.1, which doesn’t support C++11 since it’s developed in 2007.
What are clang and LLVM?
So what makes my code work? What are clang and LLVM? Let’s go a little deeper.
Clang /ˈklæŋ/[4] is a compiler front end for the programming languages C, C++, Objective-C, Objective-C++, OpenMP,[5] OpenCL, and CUDA. It uses LLVM as its back end and has been part of the LLVM release cycle since LLVM 2.6.
from Wikipedia
The LLVM compiler infrastructure project (formerly Low Level Virtual Machine) is a “collection of modular and reusable compiler and toolchain technologies” used to develop compiler front ends and back ends. LLVM is written in C++ and is designed for compile-time, link-time, run-time, and “idle-time” optimization of programs written in arbitrary programming languages. Originally implemented for C and C++, the language-agnostic design of LLVM has since spawned a wide variety of front ends: languages with compilers that use LLVM include ActionScript, Ada, C#, Common Lisp, Crystal, D, Delphi, Fortran, OpenGL Shading Language, Halide, Haskell, Java bytecode, Julia, Lua, Objective-C, Pony, Python, R, Ruby, Rust, CUDA, Scala, and Swift.
from Wikipedia
All right. I just figured out when I run the g++, llvm-gcc is indeed running, which is the gcc frontend, and then the llvm backend. On the other side, clang++ is running clang, which is the clang frontend and then the llvm backend. Following
So, my g++ is actually using clang-LLVM 8.0, which supports c++11, even c++14.
DONE.
Further questions
what are front-end compiler and back-end complier? I should’ve taken the complier coursework during my B.S :(
who made the clang & LLVM? are they open-source projects?
vector<int> twoSum(vector<int>& nums, int target) {
// 1. O(n^2) solution
// Brute-force : pick the two number;
vector<int> answer = vector<int>();
for (int i=0; i < nums.size(); i++){
int pivot = nums[i];
for (int j=i + 1; j < nums.size(); j++){
int sum = pivot + nums[j];
if(sum == target){
answer.push_back(i);
answer.push_back(j);
return answer;
}
}
}
return answer;
}
}
Hash table using solution : O(n)
The key idea is the complement of an answer number must exist (an answer number + the complement number = target). So we just should minimize the time to find the complement number, which I found a hash table is the one. Search the complement number in the existing hash table, and if not found, add the number to the hash table. DONE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
// 2. O(n) solution
// using hash table
unordered_map<int, int> hash_table;
vector<int> answer = vector<int>();
for (int i=0; i < nums.size(); i++){
int complement = target - nums[i];
if (hash_table.find(complement) != hash_table.end()){
기본적인 Objective-C를 학습하는 데 있어서 필요한 튜토리얼들을 대충 정리해 보았다.
Objective-C의 기본개념 기본적인 Objective C의 문법과 개념에 대해서 다루고 있는 페이지다. Scott Stevenson의 Objective-C 튜토리얼을 번역한 글이다. 전체적으로 C에서 Objective-C가 어떤 부분에서 다르고, 실제 iOS 어플리케이션을 만들 때 어떤 부분들이 필요한지에 대해서 다루었다. 다만, 기초적인 Tutorial이라고 표현하기에 예제가 부족하고, 개념을 주로 설명하는 편이어서 Objective-C의 지식이 전무한 상태에서 따라가기에는 조금 안 좋아 보인다. 어느 정도 Objective-C의 개념을 훑어보기에 좋다.
Objective-C 따라하기 강좌 기초적인 예제 중심으로 Objective-C 프로그램을 개발하기에 필요한 부분들을 학습할 수 있는 Tutorial이다. 무작정 따라하기에는 쉽고, 빨리 따라할 수 있는 구성으로 되어 있으니, 추천할 만하다. 그림도 이래저래 많이 친절하게 들어가 있어서 따라가기에 좋다. 다만 C를 이미 학습한 사람들에게 있어서 조금 중복되는 부분이 있을 수 있으니, 이는 감안하고 보는 게 좋을 듯 하다.
매크로인 #define를 수식이나 상수에 사용하는 것은 떄때로 예측할 수 없는 결과를 가져올 수 있으며 , 디버깅에 있어서 비효율적이다. 일례로 아래와 같은 컴파일 에러를 생각해 보자.
1
2
3
// Bad Example
#define ASPECT_RATIO 1.563
int ratio = ASPECT_RATIO / 0;
컴파일러로 코드가 넘어간 후에는ASPECT_RATIO가 symbolic name으로 남지 않고,숫자 상수로 대체되어 버린다. 때문에 컴파일러의 기호 테이블에 들어가 있기 때문에 컴파일 에러라도 나면, 복잡한 코드에서는 이를 바로잡기가 쉽지 않다. 특히나 매크로 함수는 큰 재앙이 될 수도 있다.
위와 함수의 경우 a는 7이 되고, 아래의 경우는 6이 되어버린다. 의도되지 않은 결과가 나와버린다.
상수를 선언하는 올바른 코드는 아래와 같다.
1
2
// Good Example
constdouble AspectRatio = 1.653;
클래스 안에서 상수를 사용하고 싶을 때는 static const 혹은 enum을 사용하자.
1
2
3
4
5
6
// Good Example
class ConstEstimate{
private:
staticconstdouble FudgeFactor = 1.35;
enum { NumTurns = 5};
}
매크로 함수의 경우, template function을 사용하면 매크로의 효율적인 코드의 측면을 가져갈 수 있다.
1
2
3
4
5
6
// Good Example
template<typename T>
inlinevoidcallWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
항목 3. 낌새만 보이면 const를 들이대 보자.
const는 컴파일러가 해당 변수 값에 대한 제약을 단단히 지켜준다는 점에서 강력하고 매력적인 도구이다. 다양한 const의 사용 예를 분석해 보자.
1
2
3
4
char *p = greeting; // non-const pointer, non-const data
constchar *p = greeting; // non-const pointer, const data
char *const p = greeting; // const pointer, non-const data
constchar *const p = greeting // const pointer, const data
규칙이 조금은 헷갈리긴 하지만 표시를 기준으로, 왼쪽에 const는 data를 상수로 취취한다. 반면 오른쪽에 있는 const는 포인터 자체를 상수로 취하게 된다. 이는 다음 예를 통해 좀 더 명확히 구분이 가능하다.
1
2
voidf1(constint *pw); // non-const pointer, const data
voidf2(intconst *pw); // non-const pointer, const data
위의 두 가지 경우에 대해서 모두 가능한 문법이며, 둘 다 int 형의 data가 상수임을 의미한다. f1 방식이 일반적이긴 하나, 둘 다 옳은 표현식이므로 기억해두자.
상수 객체를 생성할 경우에는 그에 맞추어 상수 멤버함수도 정의해줄 필요가 있다. 다음 예제를 보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
class TextBlock{
public:
constchar& operator[](std::size_t pos) const
{ return text[position];}
char& operator[](std::size_t pos)
{ return text[position];}
}
intmain(){
TextBlock tb("Hello");
std::cout << tb[0];
const TextBlock ctb("World");
std::cout << ctb[0];
return0;
}
const char& operator[] (std::size_t pos) const 에서 중요한 점은 앞의 const는 return 값인 char&가 상수임을 뜻한다. 반면 뒤의 const는 이 멤버 함수가 상수형으로 정의되었으며, 이는 상수 객체에 대해서 적용되는 함수임을 나타내는 부분이다.
추가적으로 공부가 더 필요한 부분
비트수준 상수성(bitwise constness) / 논리적 상수성(logical constness)
const_cast, static_cast의 사용 방법 및 사용 예시 이해
항목 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자.
초기화 되지 않은 채 생성된 변수들은 어디에선가 큰 문제를 일으킬 소지가 다분하다. 정의되지 않은 동작이 발생할 가능성이 높기 때문이다. 최악의 경우에는 어떤 플랫폼에서 미초기화 객체를 읽기만 해도 프로그램이 다운되기도 한다. 디버깅을 최대한 줄이기 위해서는 초기화를 하는 것이 효과적이다.
built-in type의 객체들은 직접 손으로 초기화하자.
생성자에서는 멤버 초기화 리스트를 사용하자.
non-local한 객체는 local하게 바꾸어 사용하자. (non-local한 객체를 만들면 translation unit 단계에서 정의되지 않은 동작이 일어날 수 있다.)
Bad Example global한 변수인 tfs가 중간에 컴파일러 상 어떤 멤버 초기화 과정을 뒤죽박죽으로 할 지 알 수 없어서 위험하다.
1
2
3
4
5
6
7
class FileSystem{
public:
std::size_t numDisks() const;
...
}
extern FileSystem tfs;
std::sizet disks = tfs.numDisks(); // bad Example
Good Example tfs()가 local하게 선언되어 있으며, 이는 C++ 컴파일러상 반드시 멤버 초기화 과정을 거치므로 안전하다.
1
2
3
4
5
6
7
8
9
10
class FileSystem{
public:
std::size_t numDisks() const;
...
}
FileSystem& tfs(){
static FileSYstem fs;
return fs;
}
std::sizet disks = tfs().numDisks(); // good example