c和c++的關系
c是面向過程的語言,c++是在c的基礎上擴展的面向對象的編程語言。
c++具備c的所有功能,對c的庫完全兼容。
c++的標准在98年確定,在那之前已經有一些庫大量使用。
新標准中,推出了名稱空間的概念,既是為了方便人們使用新標准的同時,不用大量修改之前的代碼,對之前的代碼兼容,同時可以有效的避免名稱沖突。
舊標准中以.h結尾
新標准沒有.h
舊標准中可以直接包含c的庫文件,編譯器會附帶c的兼容庫實現
新標准中有一樣的c庫子模塊支持,命名方式變更為:原stdio.h,新cstdio,即前面+c,后面去掉.h
C++標准庫(C++ Standard Library),是類庫和函數的集合。
C++編譯器廠商根據C++標准委員會官方的ISO規范並將其轉化為代碼。
C++編譯器廠商在實現C++標准庫過程中必須依賴其不同操作系統所提供的系統調用接口,因此每個平台都有其自己的C++標准庫實現。
C++標准庫的特點如下:
A、C++標准庫不是C++語言標准的一部分,由類庫和函數庫組成。
B、C++標准庫中定義的類和對象都位於std命名空間中。
C、C++標准庫的頭文件都不帶.h后綴。
D、C++標准庫涵蓋了C庫的功能
E、C++標准庫中包含一個涵蓋C庫功能的子庫,通常頭文件以c開頭,如#include <cmath>,#include <cstring>等。
如何理解名稱空間
命名空間存在的目的是為了解決源代碼中的重名問題。比如你寫代碼的時候需要用到矩陣計算,於是你定義了一個類,叫做Matrix。然后你引入的第三方庫中,也有一個叫做Matrix的類,於是乎就重名了。為了解決這個問題,只需要把它們放在不同的命名空間里,比如你的叫做foo::Matrix, 第三方庫的叫做third_party::Matrix,這樣它們就有了不同的名字,編譯器就可以正確識別出你在代碼中用的Matrix是哪一個。
這個時候如果你同時使用了using namespace foo,using namespace third_party,就又會使這兩個不同的類具有相同的標識符。因此在良好的編程風格中,盡可能的避免使用using namespace,或者僅在翻譯單元(可以理解為是一個cpp文件)內、函數內、類內使用(using具體的對象、函數)。
第二個問題是是不是所有的程序名字都要在std中。恰恰相反,C++標准禁止用戶自己擴充std命名空間,所以用戶的代碼應該是處於非std空間中,例如默認命名空間:: 。但是,事實上每一個編譯器都支持用戶在std空間中定義自己的類、函數、對象,因此在std實現自定義類的哈希函數也是可以編譯通過的,盡管這是一個違背標准的行為。
在刷算法時,可以隨意一點,按照這種方式使用
using namespace std; // avoid as too indiscriminate(隨意)
嚴謹一點可以這樣,最大限度地避免沖突的產生
using std::cin;
using std::cout;
using std::endl;
int x;
cin >> x;
cout << x << endl;
或者這樣
int x;
std::cin >> x ;
std::cout << x << std::endl;
However,
using namespace std;
is considered a bad practice because you are practically importing the whole standard namespace, thus opening up a lot of possibilities for name clashes. It is better to import only the stuff you are actually using in your code, like
using std::string;
字符串類型
C語言不支持真正意義上的字符串,但可以使用字符數組和一組函數實現字符串操作。C語言不支持自定義類型,因此也不能定義字符串類型。
C++語言可以自定義類型,可以通過類完成字符串類型的定義,但C++語言也沒有原生的字符串類型。C++語言通過C++標准庫提供的string類型實現對字符串類型的支持。string類的特性如下:
A、string直接支持字符串連接
B、string直接支持字符串的大小比較
C、string直接支持子串查找和提取
D、string直接支持字符串的插入和替換
變量聲明與定義
extern int i; //聲明,不是定義
int i; //聲明,也是定義
定義只能出現在一處。也就是說,不管是 int a 還是 int a=0 都只能出現一次,而 extern int a 可以出現很多次。
當你要引用一個全局變量的時候,你就要聲明 extern int a 這時候 extern 不能省略,因為省略了,就變成 int a 這是一個定義,不是聲明。
前綴指定基數:
- 0x 或 0X 表示十六進制,
- 0 表示八進制,
- 0b表示二進制
- 不帶前綴則默認表示十進制
后綴是 U 和 L 的組合,U 表示無符號整數(unsigned),L 表示長整數(long)。后綴可以是大寫,也可以是小寫,U 和 L 的順序任意。
結構數據類型
結構數據類型允許構造由多個基礎數據類型組合而成的復雜結構,結構數據類型為面向對象的藍本。以下的結構數據類型通過指針實現了二叉樹結構
typedef struct Bintree {
int data;
struct bintree *lchild; // left child of the node
struct bintree *rchild; // right child of the node
} bintree; // 自定義 bintree 類型
&&,||,&,|
&&:邏輯與,前后條件同時滿足表達式為真
||:邏輯或,前后條件只要有一個滿足表達式為真
&:按位與
|:按位或
&&和||是邏輯運算,&與|是位運算
*,&
*的作用
1.乘號(Multiply)
2.聲明指針(Pointer Statement)
//就是聲明變量a是5,把a的地址附到指針ptr上
int a =5; int* ptr=&a;
3.解引用 (Dereference)
*ptr 單獨拿出來就是找出 ptr指針指向的值,按照第二點的說法就是5
&的作用
&叫做取地址符號
一般指針只能接受一個內存地址而不能接受一個值
//錯誤表達,指針不能接受一個值
int a =5; int* ptr=a;
//正確表達,把a的地址給指針ptr
int a =5; int* ptr=&a;
案例:
數據結構偽代碼理解
比如定義鏈表時:
typedef struct Node{
}Node,*Linklist;
在創建函數時候這樣,
int creatlist(Linklist &L){}
用這個函數時候需要這樣寫
creatlist(L);
而定義順序表時
typedef struct{
}List;
創建函數時候
int creatlist(List *l){}
用函數的時候
creatlist(&l);
解答
不關引用和題主C語言不好的事,事情應該是這樣的:
並不是你的教材和你的老師講錯了,這樣的代碼是有意為之。但是程序又跑不起來,那問題出在哪呢。問題就在於大多數數據結構教材一開始就告訴了你,
本書的算法都是用類C語言偽碼實現的,並非是嚴格意義上的C語言。在創建函數時候這樣,
int creatlist(Linklist &L){}
用這個函數時候需要這樣寫creatlist(L);
為什么這么創建(定義)函數呢?因為編書人想告訴你的是函數的參數並非變量本身,而是存放變量的地址(有些答主學了C++,看到&就是引用,真的,你太敏感了)。
為什么要這么調用呢?因為函數的定義,函數調用需要傳一個地址進去,那么傳一個指針進去是理所當然的。再來看這段代碼。而定義順序表時
typedef struct{
}List;
創建函數時候
int creatlist(List *l){}
用函數的時候
creatlist(&l);
WTF?看起來跟上面的定義和調用格式都完全不一樣哎,又懵逼了...其實是這樣的:為什么這樣創建(定義)函數呢?和上其實同理,如果這樣寫,typedef struct{
}List;
int creatlist(List l){}就是在說你只是傳了一個結構體進去。所以作者加個*,是想告訴你這里傳進去的是個順序表。
為什么這么調用呢?還是因為定義,函數需要一個地址,那么我們就傳一個地址進去。綜上所述,這幾段代碼肯定是跑不起來的,因為根本不是C語言代碼,只是偽代碼而已,那作者是吃多了才這么寫么?不是。作者只是想簡化用來實現算法的語言,因為數據結構中選用的語言根本不是重點,重點是各種數據結構的思想。換句話說作者沒想讓你把程序跑起來,作者只是想讓你能更容易懂。說到這里我想你應該很明白了,程序跑不起來書和老師都沒有錯(也不是某些答主說的C++中的引用或者你的C語言學得不好),既然作者已經將語法簡化得不能再簡化了,何妨不將教材上的偽代碼充分理解,然后選取一門語言自己實現它呢?或許作者選用偽代碼來講述也有這一層原因(逼你自己動手)吧。
參考鏈接:請問 C 語言中 & 和 * 的用法? - 陳思定的回答 - 知乎
gcc,g++,gdb,cc
gcc and g++ are compiler-drivers of the GNU Compiler Collection (which was once upon a time just the GNU C Compiler).Even though they automatically determine which backends (cc1 cc1plus ...) to call depending on the file-type, unless overridden with -x language, they have some differences.The probably most important difference in their defaults is which libraries they link against automatically.According to GCC's online documentation link options and how g++ is invoked, g++ is equivalent to gcc -xc++ -lstdc++ -shared-libgcc (the 1st is a compiler option, the 2nd two are linker options). This can be checked by running both with the -v option (it displays the backend toolchain commands being run).
-
GCC: GNU Compiler Collection
- Referrers to all the different languages that are supported by the GNU compiler.
-
gcc: GNU C Compiler
-
g++: GNU C++ Compiler
The main differences:
- gcc will compile: *.c , *.cpp files as C and C++ respectively.
- g++ will compile: *.c , *.cpp files but they will all be treated as C++ files.
- Also if you use g++ to link the object files it automatically links in the std C++ libraries (gcc does not do this).
- gcc compiling C files has fewer predefined macros(預定義宏命令).
- gcc compiling *.cpp and g++ compiling *.c/*.cpp files has a few extra macros.
