C基础-入门

C基础-入门

不得不说学习C/C++将是一个噩梦般的过程,不过学习带来的成果也是不可估量的,下面我们使用jetbrins的clion开发工具,重学C/C++。

环境配置

CLion的安装这里就不多说了,这里提一下,mac如果安装了XCode就不需要配置什么了,如果是Windows系统,需要安装Cygwin,在下面红框处配置Cygwin环境即可。

在这里插入图片描述

Hello World

新建项目

环境配置完成后,新建一个项目

在这里插入图片描述

可以看到,左侧菜单栏有很多选项

  • C++ Execuable:创建一个C++项目
  • C++ Library:创建一个C++依赖库项目
  • C Execuable:创建一个C项目
  • C Library:创建一个C依赖库项目

这里我们从C语言开始学起,创建一个C Execuable,标准库选择默认的C99即可。可以看到,创建完成后,编辑器为我们创建了两个文件

在这里插入图片描述

CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(untitled1 C)

set(CMAKE_C_STANDARD 99)

add_executable(untitled1 main.c)

其中CMakeLists.txt是一个配置文件,作用相当于androidstudio的settings.gradle,add_executable中可以有多个参数,参数之间以空格分开,第一个参数就是项目目录,后面的参数就是c文件了。

main.c
#include <stdio.h>

int main() {
    printf("Hello, World!你好\n");
    return 0;
}

第一行#include,导入头文件,相当于android的import关键字,后面以<>符号括起来的包代表系统包,以""符号括起来的包代表我们自己定义的包。

stdio.h头文件包含了printf方法,所以下面才能够调用。

这时项目就可以运行起来了

在这里插入图片描述

中文乱码

输出的中文文字可能会有乱码的问题

在这里插入图片描述

这里有个奇怪的问题:

  • 右下角有个UTF-8编码格式,如果是windows系统,默认的是UTF-8,需要改成GBK编码

  • 如果是macOS,默认的就是GBK,需要转成UTF-8

这时会弹出一个对话框,点击convert,再次运行即可。

函数

在c语言中,执行顺序是死板的,如果我们调用的函数在当前函数下面,编译器是会报错的,比如:

在这里插入图片描述

这是把test函数放到main函数上面即可。

在这里插入图片描述

函数声明

如果非要在下面定义函数,那么就需要在最上面进行函数声明:

void test();

int main() {
    printf("main\n");

    test();
    return 0;
}

void test() {
    printf("test\n");
}

这样也是可以的

占位符

如果需要打印某个变量,跟java不同的是,c中需要使用占位符。比如:

int i = 100;
printf(i);

这样系统将会报错

在这里插入图片描述

我这里没有报错信息,但是可以看到,code为139,非正常退出。那应该怎么办呢?其实跟java中的占位符是一样的

int i = 100;
printf("%d\n", i);

如果是int类型,那么使用%d进行占位,这里我进行了简单的整理,每个数据类型都需要哪些占位符呢

类型占位符
int or short%d
double%lf
float%f
long%ld
char%c
char*(字符串)%s
指针%p

测试一下:

int main() {
    printf("Hello, World!你好\n");

    int i = 100;
    printf("%d\n", i);

    double d = 10;
    printf("%lf\n", d);

    float f = 100;
    printf("%f\n", f);

    long l = 100;
    printf("%ld\n", l);

    short sd = 1;
    printf("%d\n", sd);

    char c = 'a';
    printf("%c\n", c);

    char *str = "kf";
    printf("%s\n", str);

    // getchar(); // 阻塞程序,不停止运行
    return 0;
}

打印

在这里插入图片描述

数据类型

新建一个c文件,测试一下数据类型所占字节,注意,一个项目里面只能有一个main入口,新建文件如果写了main函数,那么需要将其他文件的main函数注释掉

#include <stdio.h>

//
// Created by hp on 2021/2/23.
// sizeof 查看类型占用字节数
//
int main() {
    printf("int 占用字节: %lu", sizeof(int));
    printf("double 占用字节: %lu\n", sizeof(double));
    printf("char 占用字节: %lu\n", sizeof(char));
    printf("short 占用字节: %lu\n", sizeof(short));
    printf("long 占用字节: %lu\n", sizeof(long));
    return 0;
}

使用sizeof函数可以查看某个类型所占用的字节数

/Users/kangfan/work/Cwork/study_1/cmake-build-debug/study_1
int 占用字节: 4
double 占用字节: 8
float 占用字节: 4
char 占用字节: 1
short 占用字节: 2
long 占用字节: 8

Process finished with exit code 0

对象的地址

在c中,可以在变量前面使用符号&,获取该对象的地址信息:

int main() {
    int num1 = 1090;
    printf("num1的地址是 :%p\n", &num1);
    return 0;
}

可以看到打印

/Users/kangfan/work/Cwork/study_1/cmake-build-debug/study_1
num1的地址是 :0x7ffee50be768

Process finished with exit code 0

指针

在c中,可以说万物皆指针,我们定义一个变量int i = 10,这时其实就是在内存中开辟一个4字节的空间,这个空间存放了数字10,然后使用一个别名i去指向这个空间的值。

在这里插入图片描述

上面我们可以通过&拿到某个对象的地址,那么当我们知道某个地址时,怎么获取它对应的值呢?

int main() {
    int i = 100;
    double d = 200;

    // 1. 直接拿到值
    printf("i 的值是 %d\n", i);
    printf("d 的值是 %lf\n", d);


    printf("\n");


    // 2. 指针取出值, 既然万物皆地址,可以通过地址拿到值
    // 通过&获取内存地址, 比如 &i 为1000DF
    // 再通过*获取地址对应的值, &i 对应的值就是100
    printf("i 的值是 %d\n", *(&i));
    printf("d 的值是 %lf\n", *(&d));
}

使用符号*就可以获取某个地址的值,*比如(&i),获取了i对应的内存地址,在通过*(&i),获取对应得值,结果打印出来就是i的值。

i 的值是 100
d 的值是 200.000000

i 的值是 100
d 的值是 200.000000

指针变量

我们可以使用指针变量直接接收某个值的地址,在变量前面加上符号*:

int i = 100;
double d = 200l

int *intP = &i;
double *doubleP = &d;

printf("i 的值是 %d\n", *intP);
printf("d 的值是 %lf\n", *doubleP);
// 直接打印地址
printf("i 的地址是 %p\n", intP);

打印结果:

i 的值是 100
d 的值是 200.000000
i 的地址是 0x7ffedfd9a768

通过指针修改值

int main4() {

    int i = 100;
    int *pi = &i;

    printf("i === %d\n", i);

    // 直接修改i的值
    i = 200;
    printf("i === %d\n", i);

    // 直接修改i的值
    *pi = 300;
    printf("i === %d\n", i);

    return 0;
}

首先定义一个变量i = 100, pi指针指向i的地址,这时修改i的值有两种方式:

  • 直接修改: i = 200;
  • 通过指针修改: pi = 300,其实*pi就获取到了地址值,再进行修改

定义一个函数修改变量

以上原理明白了,那么定义一个函数修改当前变量是不是感觉很简单了

void changeVal(int i);
void changeP(int *i);

int main5() {
    int i = 1;
    printf("i point address === %p\n", &i);
    // 直接传值,是不能修改i的值的
    changeVal(i);
    printf("i === %d\n", i);
    
    // 通过地址修改值之后 i === 200
    changeP(&i);
    printf("i === %d\n", i);
}

// 当函数入栈时,会在内存开辟一个i的空间,
// 这时跟传递进来的i的地址是不一样的,修改了这个数是不起作用的\
// 通过打印两个i的地址即可证实
// i point address === 000000000061FE1C
// changVal i point address === 000000000061FDF0
void changeVal(int i) {
    i = 300;
    printf("changVal i point address === %p\n", &i);
}

// 把i的地址传递到这个函数中来, 在通过地址修改值
// 这时在上面打印就是修改过后的值了
void changeP(int *i) {
    *i = 200;
}

当直接给函数传值是不能修改当前变量的,只能传递地址进来才可以修改。

看一下打印结果:

/Users/kangfan/work/Cwork/study_1/cmake-build-debug/study_1
i point address === 0x7ffedff72768
changVal i point address === 0x7ffedff7272c
i === 1
i === 200


Process finished with exit code 0

main函数中i的地址是0x7ffedff72768,而直接通过传值进来的i,地址变成了0x7ffedff7272c。

进阶:交换两个变量的值

下面进行进阶,定义一个函数,交换两个变量的值:

// 先定义一个tmp,找到a地址的值,
// a地址的值赋值为b
// b地址的值再赋值为tmp即可.
void swap(int* a, int* b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

首先函数还是需要接受地址的

  • 1,定义一个临时变量tmp,赋值为a的值
  • 2,将a的地址的值改变为b的值
  • 3,载将b的地址的值改变为tmp即可。

下面我们验证一下:

void swap(int* a, int* b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main() {
    // 进阶: 根据以上原理,定义一个函数,交换两个int的值?
    int a = 10;
    int b = 20;
    swap(&a, &b); // 交换
    printf("a === %d\n", a);//a === 20
    printf("b === %d\n", b);//b === 10
    return 0;
}

打印结果:

a === 20
b === 10

总结

既然是入门,今天就少学习一点,到这里还是比较基础的,了解了指针,也才算是对c语言刚刚入门,可谓是学海无涯,付出和回报一定是成正比的,加油!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿烦大大@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值