一些 C/C++ 的知识

发布时间 2023-10-14 21:53:26作者: 爱吃砂糖橘的白龙

引用

https://zhuanlan.zhihu.com/p/100050970
https://www.sohu.com/a/300755552_120111838

gcc与g++的区别

GCC: GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAVA、Fortran、Pascal、Object-C等语言。
gcc是GCC中的GUN C Compiler(C编译器);g++是GCC中的GUN C++ Compiler(C++编译器)。
gcc和g++的主要区别

  1. 对于 .c和.cpp文件,gcc分别当做c和cpp文件编译(c和cpp的语法强度是不一样的)
  2. 对于 .c和.cpp文件,g++则统一当做cpp文件编译
  3. 使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL
  4. gcc在编译C文件时,可使用的预定义宏是比较少的
  5. gcc在编译cpp文件时/g++在编译c文件和cpp文件时(这时候gcc和g++调用的都是cpp文件的编译器),会加入一些额外的宏。
  6. 在用gcc编译c++文件时,为了能够使用STL,需要加参数 –lstdc++ ,但这并不代表 gcc –lstdc++ 和 g++等价,它们的区别不仅仅是这个。

C++面向对象的知识

  1. 实例化子类时,首先调用父类的构造函数,然后调用子类的构造函数;
  2. 可以从类的其他成员函数显式地调用构造函数和析构函数;例如:
#include <iostream>
using namespace std;
class Test{
public:
    Test() { cout << "Constructor is executed\n"; }
    ~Test() { cout << "Destructor is executed\n"; }
    void show() { 
        Test(); 
        this->~Test(); 
    }
};

int main(){
    Test t;
    t.show();
    return 0;
}

输出:

由于一个对象调用了析构函数,该对象就不再存在了; 如果为生命周期已结束的对象调用析构函数,则行为难以预测;
3. 构造函数可以是私有的,例如设计模式中经典的单例模式;
4. 可以从构造函数调用私有成员函数;

printf函数的格式化输出

int main(){
    int c,d;
    char strings[] = "hello";
    printf("------------------\n");
    for(c=4;c>=0;c--){
        d = c+1;
        printf("|%-1.*s|\n", d, strings);
    }
    printf("------------------\n");
    return 0;
}
```输出:
![](https://img2023.cnblogs.com/blog/1233571/202310/1233571-20231014213214483-503317478.png)

## 关于const char * p 和 char const * p 和 char * const p 的区别
代码:

include

using namespace std;

namespace t0
{
void test0(){
char str1[] = "Monkey";
char str2[] = "Tiger";
const char * p = NULL;

    p = str1;
    // p[0] = 'X';  //error: invalid conversion from 'const char*' to 'char' 不能修改p所指向地址的内容
    str1[0] = 'X';

    while(*p){  cout << *p << " ";  p++;        }
    cout << endl;
    
    p = str2;       // 可以修改p指向的目标
    while(*p){  cout << *p << " ";  p++;        }
    cout << endl;
}

}

namespace t1
{
void test1(){
char str1[] = "Monkey";
char str2[] = "Tiger";
char const * p = NULL;

    p = str1;
    // p[0] = 'X';  //error: invalid conversion from 'const char*' to 'char' 不能修改p所指向地址的内容
    str1[0] = 'X';

    while(*p){  cout << *p << " ";  p++;        }
    cout << endl;
    
    p = str2;       // 可以修改p指向的目标
    while(*p){  cout << *p << " ";  p++;        }
    cout << endl;
}

}

namespace t2
{
void test2(){
char str1[] = "Monkey";
char str2[] = "Tiger";
char * const p = str1;

    p[0] = 'P';     // 可以修改p所指向内存地址的内容
    cout << str1 << endl;

    // p = str2;    // error: assignment of read-only variable 'p' ,p不能指向其他内存地址
}

}

namespace t3
{
void test3(){
char str1[] = "Monkey";
char str2[] = "Tiger";
const char * const p = str1;

    // p[0] = 'P';     // error: assignment of read-only location '*(const char*)p'
    // 不可以修改p所指向内存地址的内容
    
    str1[0] = 'P';
    cout << str1 << endl;

    // p = str2;    // error: assignment of read-only variable 'p'
    // p不能指向其他内存地址
}

}

int main(int argc, char **argv){

// const char * p 和 char const * p 是一个意思 :  
t0::test0();
cout << "***********" <<endl;
t1::test1();
cout << "-----------" <<endl;
t2::test2();
cout << "+++++++++++" <<endl;

// 不允许 p 指向地址修改,也不允许修改 p 所指向地址的数据
t3::test3();

return 0;

}

效果:
![](https://img2023.cnblogs.com/blog/1233571/202310/1233571-20231014213918126-1366321680.png)
结论:
1. const char * p 和 char const * p 是一个意思,代表不能修改p指针所指向地址的内容,但可以修改p指针所指向的目标地址;
2. char * const p 代表不可以修改p指针所指向的目标地址,但可以修改p指针所指向地址的内容;
3. const char * const p 代表既不允许 p 指向地址修改,也不允许修改 p 所指向地址的数据;

## 函数同时有多个返回值
代码:

int x(int a, int b, int c){
int e,g,h;
e = a+b/c; // 12
g = ab+c; // 29
h = a
b*c; // 120
return (e,g,h);
}

int main(){
int a=12,b=2,c=5,d;
d = x(a,b,c);
printf("%d", d);
return 0;
}

做题遇到的,x函数返回()括起来的三个int整型数居然也不报错,但是实际返回值只有(e,g,h)中的最后一个数h。

## 持续更新